From 1ca28badad2f9a08713ce06100903acc1257d12c Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 20 Mar 2019 04:29:25 +0700 Subject: [PATCH 001/115] ref_soft: initial 2D drawing implementation --- r_context.c | 814 ++++++++++++++++++++++++++++++++ r_draw.c | 283 +++++++++++ r_glblit.c | 110 +++++ r_image.c | 1308 +++++++++++++++++++++++++++++++++++++++++++++++++++ r_local.h | 710 ++++++++++++++++++++++++++++ r_triapi.c | 355 ++++++++++++++ r_vgui.c | 225 +++++++++ wscript | 55 +++ 8 files changed, 3860 insertions(+) create mode 100644 r_context.c create mode 100644 r_draw.c create mode 100644 r_glblit.c create mode 100644 r_image.c create mode 100644 r_local.h create mode 100644 r_triapi.c create mode 100644 r_vgui.c create mode 100644 wscript diff --git a/r_context.c b/r_context.c new file mode 100644 index 00000000..55e8ff12 --- /dev/null +++ b/r_context.c @@ -0,0 +1,814 @@ +/* +vid_sdl.c - SDL vid component +Copyright (C) 2018 a1batross + +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 3 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. +*/ + +#include "r_local.h" + +ref_api_t gEngfuncs; +ref_globals_t *gpGlobals; +ref_instance_t RI; +gl_globals_t tr; +ref_speeds_t r_stats; +byte *r_temppool; +cvar_t *gl_emboss_scale; +viddef_t vid; +static void R_ClearScreen( void ) +{ + +} + +static qboolean IsNormalPass( void ) +{ + return RP_NORMALPASS(); +} + +static void R_IncrementSpeedsCounter( int type ) +{ + switch( type ) + { + case RS_ACTIVE_TENTS: + r_stats.c_active_tents_count++; + break; + default: + gEngfuncs.Host_Error( "R_IncrementSpeedsCounter: unsupported type %d\n", type ); + } +} + +static const byte *R_GetTextureOriginalBuffer( unsigned int idx ) +{ + /*gl_texture_t *glt = R_GetTexture( idx ); + + if( !glt || !glt->original || !glt->original->buffer ) + return NULL;*/ + + return NULL; +} + +static int R_GetBuiltinTexture( enum ref_shared_texture_e type ) +{ + switch( type ) + { + case REF_DEFAULT_TEXTURE: return tr.defaultTexture; + case REF_GRAY_TEXTURE: return tr.grayTexture; + case REF_WHITE_TEXTURE: return tr.whiteTexture; + case REF_SOLIDSKY_TEXTURE: return tr.solidskyTexture; + case REF_ALPHASKY_TEXTURE: return tr.alphaskyTexture; + default: gEngfuncs.Host_Error( "R_GetBuiltinTexture: unsupported type %d\n", type ); + } + + return 0; +} + +static void R_FreeSharedTexture( enum ref_shared_texture_e type ) +{ + int num = 0; + + switch( type ) + { + case REF_SOLIDSKY_TEXTURE: + num = tr.solidskyTexture; + tr.solidskyTexture = 0; + break; + case REF_ALPHASKY_TEXTURE: + num = tr.alphaskyTexture; + tr.alphaskyTexture = 0; + break; + case REF_DEFAULT_TEXTURE: + case REF_GRAY_TEXTURE: + case REF_WHITE_TEXTURE: + gEngfuncs.Host_Error( "R_FreeSharedTexture: invalid type %d\n", type ); + default: gEngfuncs.Host_Error( "R_FreeSharedTexture: unsupported type %d\n", type ); + } + + GL_FreeTexture( num ); +} + +/* +============= +CL_FillRGBA + +============= +*/ +static void CL_FillRGBA( float _x, float _y, float _w, float _h, int r, int g, int b, int a ) +{ + +} + +/* +============= +pfnFillRGBABlend + +============= +*/ +static void GAME_EXPORT CL_FillRGBABlend( float _x, float _y, float _w, float _h, int r, int g, int b, int a ) +{ + +} + + +qboolean Mod_ProcessRenderData( model_t *mod, qboolean create, const byte *buf ) +{ + qboolean loaded = true; + + if( create ) + { + + + switch( mod->type ) + { + case mod_studio: + // Mod_LoadStudioModel( mod, buf, loaded ); + break; + case mod_sprite: + //Mod_LoadSpriteModel( mod, buf, &loaded, mod->numtexinfo ); + break; + case mod_alias: + //Mod_LoadAliasModel( mod, buf, &loaded ); + break; + case mod_brush: + // Mod_LoadBrushModel( mod, buf, loaded ); + break; + + default: gEngfuncs.Host_Error( "Mod_LoadModel: unsupported type %d\n", mod->type ); + } + } + + if( loaded && gEngfuncs.drawFuncs->Mod_ProcessUserData ) + gEngfuncs.drawFuncs->Mod_ProcessUserData( mod, create, buf ); + + //if( !create ) + //Mod_UnloadTextures( mod ); + + return loaded; +} + +static int GL_RenderGetParm( int parm, int arg ) +{ + image_t *glt; + + switch( parm ) + { + case PARM_TEX_WIDTH: + glt = R_GetTexture( arg ); + return glt->width; + case PARM_TEX_HEIGHT: + glt = R_GetTexture( arg ); + return glt->height; + case PARM_TEX_SRC_WIDTH: + glt = R_GetTexture( arg ); + return glt->srcWidth; + case PARM_TEX_SRC_HEIGHT: + glt = R_GetTexture( arg ); + return glt->srcHeight; + case PARM_TEX_MIPCOUNT: + glt = R_GetTexture( arg ); + return glt->numMips; + case PARM_TEX_DEPTH: + glt = R_GetTexture( arg ); + return glt->depth; + case PARM_TEX_SKYBOX: + Assert( arg >= 0 && arg < 6 ); + return tr.skyboxTextures[arg]; + case PARM_TEX_SKYTEXNUM: + return tr.skytexturenum; + case PARM_TEX_LIGHTMAP: + arg = bound( 0, arg, MAX_LIGHTMAPS - 1 ); + return tr.lightmapTextures[arg]; + case PARM_WIDESCREEN: + return gpGlobals->wideScreen; + case PARM_FULLSCREEN: + return gpGlobals->fullScreen; + case PARM_SCREEN_WIDTH: + return gpGlobals->width; + case PARM_SCREEN_HEIGHT: + return gpGlobals->height; + case PARM_TEX_FLAGS: + glt = R_GetTexture( arg ); + return glt->flags; + case PARM_LIGHTSTYLEVALUE: + arg = bound( 0, arg, MAX_LIGHTSTYLES - 1 ); + return tr.lightstylevalue[arg]; + case PARM_MAX_IMAGE_UNITS: + return 1; + case PARM_REBUILD_GAMMA: + return 0;//glConfig.softwareGammaUpdate; + case PARM_SURF_SAMPLESIZE: + if( arg >= 0 && arg < WORLDMODEL->numsurfaces ) + return gEngfuncs.Mod_SampleSizeForFace( &WORLDMODEL->surfaces[arg] ); + return LM_SAMPLE_SIZE; + case PARM_SKY_SPHERE: + return gEngfuncs.CL_GetRenderParm( parm, arg ) && !tr.fCustomSkybox; + default: + return gEngfuncs.CL_GetRenderParm( parm, arg ); + } + return 0; +} + +static void R_GetDetailScaleForTexture( int texture, float *xScale, float *yScale ) +{ + image_t *glt = R_GetTexture( texture ); + + if( xScale ) *xScale = glt->xscale; + if( yScale ) *yScale = glt->yscale; +} + +static void R_GetExtraParmsForTexture( int texture, byte *red, byte *green, byte *blue, byte *density ) +{ + image_t *glt = R_GetTexture( texture ); + + if( red ) *red = glt->fogParams[0]; + if( green ) *green = glt->fogParams[1]; + if( blue ) *blue = glt->fogParams[2]; + if( density ) *density = glt->fogParams[3]; +} + + +static void R_SetCurrentEntity( cl_entity_t *ent ) +{ + RI.currententity = ent; + + // set model also + if( RI.currententity != NULL ) + { + RI.currentmodel = RI.currententity->model; + } +} + +static void R_SetCurrentModel( model_t *mod ) +{ + RI.currentmodel = mod; +} + +static float R_GetFrameTime( void ) +{ + return tr.frametime; +} + +static const char *GL_TextureName( unsigned int texnum ) +{ + return "";//return R_GetTexture( texnum )->name; +} + +const byte *GL_TextureData( unsigned int texnum ) +{ +// rgbdata_t *pic = R_GetTexture( texnum )->original; + + //if( pic != NULL ) + //return pic->buffer; + return NULL; +} + +void Mod_BrushUnloadTextures( model_t *mod ) +{ + int i; + + for( i = 0; i < mod->numtextures; i++ ) + { + texture_t *tx = mod->textures[i]; + if( !tx || tx->gl_texturenum == tr.defaultTexture ) + continue; // free slot + + //GL_FreeTexture( tx->gl_texturenum ); // main texture + //GL_FreeTexture( tx->fb_texturenum ); // luma texture + } +} + +void Mod_UnloadTextures( model_t *mod ) +{ + int i, j; + + Assert( mod != NULL ); + + switch( mod->type ) + { + case mod_studio: + //Mod_StudioUnloadTextures( mod->cache.data ); + break; + case mod_alias: + //Mod_AliasUnloadTextures( mod->cache.data ); + break; + case mod_brush: + Mod_BrushUnloadTextures( mod ); + break; + case mod_sprite: + //Mod_SpriteUnloadTextures( mod->cache.data ); + break; + default: gEngfuncs.Host_Error( "Mod_UnloadModel: unsupported type %d\n", mod->type ); + } +} + +void R_ProcessEntData( qboolean allocate ) +{ + +} + +// stubs + +void GL_SetTexCoordArrayMode() +{ + +} +void R_InitBlit(); +void GL_OnContextCreated() +{ + R_InitBlit(); + +} + +void GL_InitExtensions() +{ + +} +void GL_ClearExtensions() +{ + +} +void R_BeginFrame(qboolean clearScene) +{ +} + +void R_RenderScene() +{ + +} + +void R_EndFrame() +{ + // blit pixels with GL until engine supports REF_SOFT context + R_BlitScreen(); +} + +void R_PushScene() +{ + +} + +void R_PopScene() +{ + +} + +void GL_BackendStartFrame() +{ + +} + +void GL_BackendEndFrame() +{ + +} + +void R_AllowFog(qboolean allowed) +{ + +} + +void GL_SetRenderMode(int mode) +{ + /// TODO: table shading/blending??? + /// maybe, setup block drawing function pointers here +} + +qboolean R_AddEntity(struct cl_entity_s *pRefEntity, int entityType) +{ + // no entities support until we draw world... + return false; +} + +void CL_AddCustomBeam(cl_entity_t *pEnvBeam) +{ + // same for beams +} + +void R_ShowTextures() +{ + // textures undone too +} + +void R_ShowTree() +{ + // do we really need this here??? +} + +void R_SetupSky(const char *skyboxname) +{ + +} + +qboolean VID_ScreenShot(const char *filename, int shot_type) +{ + +} + +qboolean VID_CubemapShot(const char *base, uint size, const float *vieworg, qboolean skyshot) +{ + // cubemaps? in my softrender??? +} + +colorVec R_LightPoint(const vec3_t p0) +{ + colorVec c = {0}; + return c; +} + +void R_DecalShoot(int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale) +{ + +} + +void R_DecalRemoveAll(int texture) +{ + +} + +int R_CreateDecalList(decallist_t *pList) +{ + return 0; +} + +void R_ClearAllDecals() +{ + +} + +float R_StudioEstimateFrame(cl_entity_t *e, mstudioseqdesc_t *pseqdesc) +{ + return 0; +} + +void R_StudioLerpMovement(cl_entity_t *e, double time, vec3_t origin, vec3_t angles) +{ + +} + +void CL_InitStudioAPI() +{ + +} + +void R_InitSkyClouds(mip_t *mt, texture_t *tx, qboolean custom_palette) +{ + +} + +void GL_SubdivideSurface(msurface_t *fa) +{ + +} + +void CL_RunLightStyles() +{ + +} + +void Mod_LoadMapSprite(model_t *mod, const void *buffer, size_t size, qboolean *loaded) +{ + +} + +void Mod_StudioLoadTextures(model_t *mod, void *data) +{ + +} + +void CL_DrawParticles(double frametime, particle_t *cl_active_particles, float partsize) +{ + +} + +void CL_DrawBeams(int fTrans, BEAM *active_beams) +{ + +} + +void CL_DrawTracers(double frametime, particle_t *cl_active_tracers) +{ + +} + +qboolean R_BeamCull(const vec3_t start, const vec3_t end, qboolean pvsOnly) +{ + return false; +} + +void DrawSingleDecal(decal_t *pDecal, msurface_t *fa) +{ + +} + +float *R_DecalSetupVerts(decal_t *pDecal, msurface_t *surf, int texture, int *outCount) +{ + return NULL; +} + +void R_EntityRemoveDecals(model_t *mod) +{ + +} + +void GL_SelectTexture(int texture) +{ + +} + +void GL_LoadTexMatrixExt(const float *glmatrix) +{ + +} + +void GL_LoadIdentityTexMatrix() +{ + +} + +void GL_CleanUpTextureUnits(int last) +{ + +} + +void GL_TexGen(unsigned int coord, unsigned int mode) +{ + +} + +void GL_TextureTarget(uint target) +{ + +} + +void CL_DrawParticlesExternal(const ref_viewpass_t *rvp, qboolean trans_pass, float frametime) +{ + // no renderapi support +} + +struct mstudiotex_s *R_StudioGetTexture(cl_entity_t *e) +{ + return NULL; +} + +colorVec R_LightVec(const vec3_t start, const vec3_t end, vec3_t lightspot, vec3_t lightvec) +{ + colorVec v = {0}; + return v; +} + +int R_RenderFrame(const struct ref_viewpass_s *vp) +{ + +} + +void GL_BuildLightmaps() +{ + +} + +void Mod_SetOrthoBounds(const float *mins, const float *maxs) +{ + +} + +qboolean R_SpeedsMessage(char *out, size_t size) +{ + return false; +} + +byte *Mod_GetCurrentVis() +{ + return NULL; +} + +void R_ClearScene() +{ + +} + +void R_NewMap() +{ + +} + +void R_ScreenToWorld(const vec3_t screen, vec3_t point) +{ + +} +void GL_SetupAttributes( int safegl ) +{ + gEngfuncs.Con_Reportf( "Creating an extended GL context for debug...\n" ); + gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_FLAGS, REF_GL_CONTEXT_DEBUG_FLAG ); + + // untill we have any blitter in ref api, setup GL + gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_PROFILE_MASK, REF_GL_CONTEXT_PROFILE_COMPATIBILITY ); + gEngfuncs.GL_SetAttribute( REF_GL_DOUBLEBUFFER, 1 ); + + gEngfuncs.GL_SetAttribute( REF_GL_RED_SIZE, 5 ); + gEngfuncs.GL_SetAttribute( REF_GL_GREEN_SIZE, 6 ); + gEngfuncs.GL_SetAttribute( REF_GL_BLUE_SIZE, 5 ); +} + + + + +qboolean R_Init() +{ + gl_emboss_scale = gEngfuncs.Cvar_Get( "gl_emboss_scale", "0", FCVAR_ARCHIVE|FCVAR_LATCH, "fake bumpmapping scale" ); + // create the window and set up the context + if( !gEngfuncs.R_Init_Video( REF_GL )) // request GL context + { + gEngfuncs.R_Free_Video(); + + gEngfuncs.Host_Error( "Can't initialize video subsystem\nProbably driver was not installed" ); + return false; + } + r_temppool = Mem_AllocPool( "ref_sw zone" ); + vid.width = 1920; + vid.height = 1080; + vid.rowbytes = 1920; // rowpixels + + vid.buffer = Mem_Malloc( r_temppool, 1920*1080*sizeof( pixel_t ) ); + + R_InitImages(); + return true; +} + +void R_Shutdown() +{ + R_ShutdownImages(); + gEngfuncs.R_Free_Video(); +} + +ref_interface_t gReffuncs = +{ + R_Init, + R_Shutdown, + + GL_SetupAttributes, + GL_OnContextCreated, + GL_InitExtensions, + GL_ClearExtensions, + + R_BeginFrame, + R_RenderScene, + R_EndFrame, + R_PushScene, + R_PopScene, + GL_BackendStartFrame, + GL_BackendEndFrame, + + R_ClearScreen, + R_AllowFog, + GL_SetRenderMode, + + R_AddEntity, + CL_AddCustomBeam, + R_ProcessEntData, + + IsNormalPass, + + R_ShowTextures, + R_ShowTree, + R_IncrementSpeedsCounter, + + R_GetTextureOriginalBuffer, + GL_LoadTextureFromBuffer, + R_GetBuiltinTexture, + R_FreeSharedTexture, + GL_ProcessTexture, + R_SetupSky, + + R_Set2DMode, + R_DrawStretchRaw, + R_DrawStretchPic, + R_DrawTileClear, + CL_FillRGBA, + CL_FillRGBABlend, + + VID_ScreenShot, + VID_CubemapShot, + + R_LightPoint, + + R_DecalShoot, + R_DecalRemoveAll, + R_CreateDecalList, + R_ClearAllDecals, + + R_StudioEstimateFrame, + R_StudioLerpMovement, + CL_InitStudioAPI, + + R_InitSkyClouds, + GL_SubdivideSurface, + CL_RunLightStyles, + + R_GetSpriteParms, + R_GetSpriteTexture, + + Mod_LoadMapSprite, + Mod_ProcessRenderData, + Mod_StudioLoadTextures, + + CL_DrawParticles, + CL_DrawTracers, + CL_DrawBeams, + R_BeamCull, + + GL_RenderGetParm, + R_GetDetailScaleForTexture, + R_GetExtraParmsForTexture, + R_GetFrameTime, + + R_SetCurrentEntity, + R_SetCurrentModel, + + GL_FindTexture, + GL_TextureName, + GL_TextureData, + GL_LoadTexture, + GL_CreateTexture, + GL_LoadTextureArray, + GL_CreateTextureArray, + GL_FreeTexture, + + DrawSingleDecal, + R_DecalSetupVerts, + R_EntityRemoveDecals, + + R_UploadStretchRaw, + + GL_Bind, + GL_SelectTexture, + GL_LoadTexMatrixExt, + GL_LoadIdentityTexMatrix, + GL_CleanUpTextureUnits, + GL_TexGen, + GL_TextureTarget, + GL_SetTexCoordArrayMode, + GL_UpdateTexSize, + NULL, + NULL, + + CL_DrawParticlesExternal, + R_LightVec, + R_StudioGetTexture, + + R_RenderFrame, + GL_BuildLightmaps, + Mod_SetOrthoBounds, + R_SpeedsMessage, + Mod_GetCurrentVis, + R_NewMap, + R_ClearScene, + + TriRenderMode, + TriBegin, + TriEnd, + _TriColor4f, + TriColor4ub, + TriTexCoord2f, + TriVertex3fv, + TriVertex3f, + TriWorldToScreen, + TriFog, + R_ScreenToWorld, + TriGetMatrix, + TriFogParams, + TriCullFace, + + VGUI_DrawInit, + VGUI_DrawShutdown, + VGUI_SetupDrawingText, + VGUI_SetupDrawingRect, + VGUI_SetupDrawingImage, + VGUI_BindTexture, + VGUI_EnableTexture, + VGUI_CreateTexture, + VGUI_UploadTexture, + VGUI_UploadTextureBlock, + VGUI_DrawQuad, + VGUI_GetTextureSizes, + VGUI_GenerateTexture, +}; + +int GAME_EXPORT GetRefAPI( int version, ref_interface_t *funcs, ref_api_t *engfuncs, ref_globals_t *globals ) +{ + if( version != REF_API_VERSION ) + return 0; + + // fill in our callbacks + memcpy( funcs, &gReffuncs, sizeof( ref_interface_t )); + memcpy( &gEngfuncs, engfuncs, sizeof( ref_api_t )); + gpGlobals = globals; + + return REF_API_VERSION; +} diff --git a/r_draw.c b/r_draw.c new file mode 100644 index 00000000..aa9c8ba7 --- /dev/null +++ b/r_draw.c @@ -0,0 +1,283 @@ +/* +gl_draw.c - orthogonal drawing stuff +Copyright (C) 2010 Uncle Mike + +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 3 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. +*/ + +#include "r_local.h" + +/* +============= +R_GetImageParms +============= +*/ +void R_GetTextureParms( int *w, int *h, int texnum ) +{ + image_t *glt; + + glt = R_GetTexture( texnum ); + if( w ) *w = glt->srcWidth; + if( h ) *h = glt->srcHeight; +} + +/* +============= +R_GetSpriteParms + +same as GetImageParms but used +for sprite models +============= +*/ +void R_GetSpriteParms( int *frameWidth, int *frameHeight, int *numFrames, int currentFrame, const model_t *pSprite ) +{ + mspriteframe_t *pFrame; + + if( !pSprite || pSprite->type != mod_sprite ) return; // bad model ? + //pFrame = R_GetSpriteFrame( pSprite, currentFrame, 0.0f ); + + //if( frameWidth ) *frameWidth = pFrame->width; +// if( frameHeight ) *frameHeight = pFrame->height; + //if( numFrames ) *numFrames = pSprite->numframes; +} + +int R_GetSpriteTexture( const model_t *m_pSpriteModel, int frame ) +{ + if( !m_pSpriteModel || m_pSpriteModel->type != mod_sprite || !m_pSpriteModel->cache.data ) + return 0; + + return 0;//R_GetSpriteFrame( m_pSpriteModel, frame, 0.0f )->gl_texturenum; +} + + +/* +============= +Draw_StretchPicImplementation +============= +*/ +void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, int s2, int t2, image_t *pic) +{ + pixel_t *dest, *source; + unsigned int v, u, sv; + unsigned int height; + unsigned int f, fstep; + int skip; + + if( x < 0 ) + { + s1 += (-x)*(s2-s1) / w; + x = 0; + } + if( x + w > vid.width ) + { + s2 -= (x + w - vid.width) * (s2 - s1)/ w ; + w = vid.width - x; + } + if( y + h > vid.height ) + { + t2 -= (y + h - vid.height) * (t2 - t1) / h; + h = vid.height - y; + } + + if( !pic->pixels[0] || s1 >= s2 || t1 >= t2 ) + return; + + //gEngfuncs.Con_Printf ("pixels is %p\n", pic->pixels[0] ); + + height = h; + if (y < 0) + { + skip = -y; + height += y; + y = 0; + } + else + skip = 0; + + dest = vid.buffer + y * vid.rowbytes + x; + + for (v=0 ; vpixels[0] + sv*pic->width + s1; + if (w == s2 - s1) + memcpy (dest, source, w * 2); + else + { + f = 0; + fstep = s2*0x10000/w; + for (u=0 ; u>16]; + f += fstep; + dest[u+1] = source[f>>16]; + f += fstep; + dest[u+2] = source[f>>16]; + f += fstep; + dest[u+3] = source[f>>16]; + f += fstep; + } + } + } +} + + +/* +============= +R_DrawStretchPic +============= +*/ +void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum ) +{ + image_t *pic = R_GetTexture(texnum); +// GL_Bind( XASH_TEXTURE0, texnum ); + if( s2 > 1 || t2 > 2 ) + return; + if( w <= 0 || h <= 0 ) + return; + R_DrawStretchPicImplementation(x,y,w,h, pic->width * s1, pic->height * t1, pic->width * s2, pic->height * t2, pic); +} + +/* +============= +Draw_TileClear + +This repeats a 64*64 tile graphic to fill the screen around a sized down +refresh window. +============= +*/ +void R_DrawTileClear( int texnum, int x, int y, int w, int h ) +{ + int tw, th, x2, i, j; + image_t *pic; + pixel_t *psrc, *pdest; + + //GL_SetRenderMode( kRenderNormal ); + _TriColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); + GL_Bind( XASH_TEXTURE0, texnum ); + + pic = R_GetTexture( texnum ); + + tw = pic->width; + th = pic->height; + if (x < 0) + { + w += x; + x = 0; + } + if (y < 0) + { + h += y; + y = 0; + } + if (x + w > vid.width) + w = vid.width - x; + if (y + h > vid.height) + h = vid.height - y; + if (w <= 0 || h <= 0) + return; + + x2 = x + w; + pdest = vid.buffer + y*vid.rowbytes; + for (i=0 ; ipixels[0] + tw * ((i+y)&63); + for (j=x ; jwidth = cols; + tex->height = rows; +} + +/* +=============== +R_Set2DMode +=============== +*/ +void R_Set2DMode( qboolean enable ) +{ + if( enable ) + { +// if( glState.in2DMode ) + // return; +#if 0 + // set 2D virtual screen size + pglViewport( 0, 0, gpGlobals->width, gpGlobals->height ); + pglMatrixMode( GL_PROJECTION ); + pglLoadIdentity(); + pglOrtho( 0, gpGlobals->width, gpGlobals->height, 0, -99999, 99999 ); + pglMatrixMode( GL_MODELVIEW ); + pglLoadIdentity(); + + GL_Cull( GL_NONE ); + + pglDepthMask( GL_FALSE ); + pglDisable( GL_DEPTH_TEST ); + pglEnable( GL_ALPHA_TEST ); + pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); +#endif + + // glState.in2DMode = true; + RI.currententity = NULL; + RI.currentmodel = NULL; + } + else + { +#if 0 + pglDepthMask( GL_TRUE ); + pglEnable( GL_DEPTH_TEST ); + glState.in2DMode = false; + + pglMatrixMode( GL_PROJECTION ); + GL_LoadMatrix( RI.projectionMatrix ); + + pglMatrixMode( GL_MODELVIEW ); + GL_LoadMatrix( RI.worldviewMatrix ); + + GL_Cull( GL_FRONT ); +#endif + } +} diff --git a/r_glblit.c b/r_glblit.c new file mode 100644 index 00000000..9e8214d1 --- /dev/null +++ b/r_glblit.c @@ -0,0 +1,110 @@ +#include "r_local.h" +#include "../ref_gl/gl_export.h" + + +/* +======================== +DebugCallback + +For ARB_debug_output +======================== +*/ +static void APIENTRY GL_DebugOutput( GLuint source, GLuint type, GLuint id, GLuint severity, GLint length, const GLcharARB *message, GLvoid *userParam ) +{ + switch( type ) + { + case GL_DEBUG_TYPE_ERROR_ARB: + gEngfuncs.Con_Printf( S_OPENGL_ERROR "%s\n", message ); + break; + case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB: + gEngfuncs.Con_Printf( S_OPENGL_WARN "%s\n", message ); + break; + case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB: + gEngfuncs.Con_Printf( S_OPENGL_WARN "%s\n", message ); + break; + case GL_DEBUG_TYPE_PORTABILITY_ARB: + gEngfuncs.Con_Reportf( S_OPENGL_WARN "%s\n", message ); + break; + case GL_DEBUG_TYPE_PERFORMANCE_ARB: + gEngfuncs.Con_Printf( S_OPENGL_NOTE "%s\n", message ); + break; + case GL_DEBUG_TYPE_OTHER_ARB: + default: + gEngfuncs.Con_Printf( S_OPENGL_NOTE "%s\n", message ); + break; + } +} +int tex; + +#define LOAD(x) p##x = gEngfuncs.GL_GetProcAddress(#x) +void R_InitBlit() +{ + LOAD(glBegin); + LOAD(glEnd); + LOAD(glTexCoord2f); + LOAD(glVertex2f); + LOAD(glEnable); + LOAD(glDisable); + LOAD(glTexImage2D); + LOAD(glOrtho); + LOAD(glMatrixMode); + LOAD(glLoadIdentity); + LOAD(glViewport); + LOAD(glBindTexture); + LOAD(glDebugMessageCallbackARB); + LOAD(glDebugMessageControlARB); + LOAD(glGetError); + LOAD(glGenTextures); + LOAD(glTexParameteri); + + if( gpGlobals->developer ) + { + gEngfuncs.Con_Reportf( "Installing GL_DebugOutput...\n"); + pglDebugMessageCallbackARB( GL_DebugOutput, NULL ); + + // force everything to happen in the main thread instead of in a separate driver thread + pglEnable( GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB ); + } + + // enable all the low priority messages + pglDebugMessageControlARB( GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, true ); + pglGenTextures( 1, &tex ); +} + + +void R_BlitScreen() +{ + //memset( vid.buffer, 10, vid.width * vid.height ); + pglBindTexture(GL_TEXTURE_2D, tex); + pglViewport( 0, 0, gpGlobals->width, gpGlobals->height ); + pglMatrixMode( GL_PROJECTION ); + pglLoadIdentity(); + pglOrtho( 0, gpGlobals->width, gpGlobals->height, 0, -99999, 99999 ); + pglMatrixMode( GL_MODELVIEW ); + pglLoadIdentity(); + + pglEnable( GL_TEXTURE_2D ); + pglBindTexture(GL_TEXTURE_2D, tex); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + //gEngfuncs.Con_Printf("%d\n",pglGetError()); + pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vid.width, vid.height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, vid.buffer ); + //gEngfuncs.Con_Printf("%d\n",pglGetError()); + pglBegin( GL_QUADS ); + pglTexCoord2f( 0, 0 ); + pglVertex2f( 0, 0 ); + + pglTexCoord2f( 1, 0 ); + pglVertex2f( vid.width, 0 ); + + pglTexCoord2f( 1, 1 ); + pglVertex2f( vid.width, vid.height ); + + pglTexCoord2f( 0, 1 ); + pglVertex2f( 0, vid.height ); + pglEnd(); + pglDisable( GL_TEXTURE_2D ); + gEngfuncs.GL_SwapBuffers(); +} diff --git a/r_image.c b/r_image.c new file mode 100644 index 00000000..166060bc --- /dev/null +++ b/r_image.c @@ -0,0 +1,1308 @@ +/* +gl_image.c - texture uploading and processing +Copyright (C) 2010 Uncle Mike + +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 3 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. +*/ + +#include "r_local.h" + +#define TEXTURES_HASH_SIZE (MAX_TEXTURES >> 2) + +static image_t r_images[MAX_TEXTURES]; +static image_t* r_imagesHashTable[TEXTURES_HASH_SIZE]; +static uint r_numImages; + +#define IsLightMap( tex ) ( FBitSet(( tex )->flags, TF_ATLAS_PAGE )) +/* +================= +R_GetTexture + +acess to array elem +================= +*/ +image_t *R_GetTexture( unsigned int texnum ) +{ + ASSERT( texnum >= 0 && texnum < MAX_TEXTURES ); + return &r_images[texnum]; +} + +/* +================= +GL_Bind +================= +*/ +void GL_Bind( int tmu, unsigned int texnum ) +{ + image_t *texture; + + texture = &r_images[texnum]; +} + +/* +================= +GL_ApplyTextureParams +================= +*/ +void GL_ApplyTextureParams( image_t *tex ) +{ + + Assert( tex != NULL ); +} + +/* +================= +GL_UpdateTextureParams +================= +*/ +static void GL_UpdateTextureParams( int iTexture ) +{ + image_t *tex = &r_images[iTexture]; + + Assert( tex != NULL ); + + if( !tex->pixels) return; // free slot + + GL_Bind( XASH_TEXTURE0, iTexture ); +} + +/* +================= +R_SetTextureParameters +================= +*/ +void R_SetTextureParameters( void ) +{ + int i; + + // change all the existing mipmapped texture objects + for( i = 0; i < r_numImages; i++ ) + GL_UpdateTextureParams( i ); +} + + +/* +================== +GL_CalcImageSize +================== +*/ +static size_t GL_CalcImageSize( pixformat_t format, int width, int height, int depth ) +{ + size_t size = 0; + + // check the depth error + depth = Q_max( 1, depth ); + + switch( format ) + { + case PF_RGB_24: + case PF_BGR_24: + size = width * height * depth * 3; + break; + case PF_BGRA_32: + case PF_RGBA_32: + size = width * height * depth * 4; + break; + case PF_DXT1: + size = (((width + 3) >> 2) * ((height + 3) >> 2) * 8) * depth; + break; + case PF_DXT3: + case PF_DXT5: + case PF_ATI2: + size = (((width + 3) >> 2) * ((height + 3) >> 2) * 16) * depth; + break; + } + + return size; +} + +/* +================== +GL_CalcTextureSize +================== +*/ +static size_t GL_CalcTextureSize( int width, int height, int depth ) +{ + return width * height * 2; +} + +static int GL_CalcMipmapCount( image_t *tex, qboolean haveBuffer ) +{ + int width, height; + int mipcount; + + Assert( tex != NULL ); + + if( !haveBuffer ) + return 1; + + // generate mip-levels by user request + if( FBitSet( tex->flags, TF_NOMIPMAP )) + return 1; + + // mip-maps can't exceeds 4 + for( mipcount = 0; mipcount < 4; mipcount++ ) + { + width = Q_max( 1, ( tex->width >> mipcount )); + height = Q_max( 1, ( tex->height >> mipcount )); + if( width == 1 && height == 1 ) + break; + } + + return mipcount + 1; +} + +/* +================ +GL_SetTextureDimensions +================ +*/ +static void GL_SetTextureDimensions( image_t *tex, int width, int height, int depth ) +{ + int maxTextureSize = 1024; + int maxDepthSize = 1; + + Assert( tex != NULL ); + + // store original sizes + tex->srcWidth = width; + tex->srcHeight = height; + + if( width > maxTextureSize || height > maxTextureSize || depth > maxDepthSize ) + { + while( width > maxTextureSize || height > maxTextureSize ) + { + width >>= 1; + height >>= 1; + } + } + + // set the texture dimensions + tex->width = Q_max( 1, width ); + tex->height = Q_max( 1, height ); + tex->depth = Q_max( 1, depth ); +} + +/* +=============== +GL_SetTextureTarget +=============== +*/ +static void GL_SetTextureTarget( image_t *tex, rgbdata_t *pic ) +{ + Assert( pic != NULL ); + Assert( tex != NULL ); + + // correct depth size + pic->depth = Q_max( 1, pic->depth ); + tex->numMips = 0; // begin counting + + // correct mip count + pic->numMips = Q_max( 1, pic->numMips ); +} + +/* +=============== +GL_SetTextureFormat +=============== +*/ +static void GL_SetTextureFormat( image_t *tex, pixformat_t format, int channelMask ) +{ + qboolean haveColor = ( channelMask & IMAGE_HAS_COLOR ); + qboolean haveAlpha = ( channelMask & IMAGE_HAS_ALPHA ); + + Assert( tex != NULL ); + tex->transparent = !!( channelMask & IMAGE_HAS_ALPHA ); +} + +/* +================= +GL_ResampleTexture + +Assume input buffer is RGBA +================= +*/ +byte *GL_ResampleTexture( const byte *source, int inWidth, int inHeight, int outWidth, int outHeight, qboolean isNormalMap ) +{ + uint frac, fracStep; + uint *in = (uint *)source; + uint p1[0x1000], p2[0x1000]; + byte *pix1, *pix2, *pix3, *pix4; + uint *out, *inRow1, *inRow2; + static byte *scaledImage = NULL; // pointer to a scaled image + vec3_t normal; + int i, x, y; + + if( !source ) return NULL; + + scaledImage = Mem_Realloc( r_temppool, scaledImage, outWidth * outHeight * 4 ); + fracStep = inWidth * 0x10000 / outWidth; + out = (uint *)scaledImage; + + frac = fracStep >> 2; + for( i = 0; i < outWidth; i++ ) + { + p1[i] = 4 * (frac >> 16); + frac += fracStep; + } + + frac = (fracStep >> 2) * 3; + for( i = 0; i < outWidth; i++ ) + { + p2[i] = 4 * (frac >> 16); + frac += fracStep; + } + + if( isNormalMap ) + { + for( y = 0; y < outHeight; y++, out += outWidth ) + { + inRow1 = in + inWidth * (int)(((float)y + 0.25f) * inHeight / outHeight); + inRow2 = in + inWidth * (int)(((float)y + 0.75f) * inHeight / outHeight); + + for( x = 0; x < outWidth; x++ ) + { + pix1 = (byte *)inRow1 + p1[x]; + pix2 = (byte *)inRow1 + p2[x]; + pix3 = (byte *)inRow2 + p1[x]; + pix4 = (byte *)inRow2 + p2[x]; + + normal[0] = MAKE_SIGNED( pix1[0] ) + MAKE_SIGNED( pix2[0] ) + MAKE_SIGNED( pix3[0] ) + MAKE_SIGNED( pix4[0] ); + normal[1] = MAKE_SIGNED( pix1[1] ) + MAKE_SIGNED( pix2[1] ) + MAKE_SIGNED( pix3[1] ) + MAKE_SIGNED( pix4[1] ); + normal[2] = MAKE_SIGNED( pix1[2] ) + MAKE_SIGNED( pix2[2] ) + MAKE_SIGNED( pix3[2] ) + MAKE_SIGNED( pix4[2] ); + + if( !VectorNormalizeLength( normal )) + VectorSet( normal, 0.5f, 0.5f, 1.0f ); + + ((byte *)(out+x))[0] = 128 + (byte)(127.0f * normal[0]); + ((byte *)(out+x))[1] = 128 + (byte)(127.0f * normal[1]); + ((byte *)(out+x))[2] = 128 + (byte)(127.0f * normal[2]); + ((byte *)(out+x))[3] = 255; + } + } + } + else + { + for( y = 0; y < outHeight; y++, out += outWidth ) + { + inRow1 = in + inWidth * (int)(((float)y + 0.25f) * inHeight / outHeight); + inRow2 = in + inWidth * (int)(((float)y + 0.75f) * inHeight / outHeight); + + for( x = 0; x < outWidth; x++ ) + { + pix1 = (byte *)inRow1 + p1[x]; + pix2 = (byte *)inRow1 + p2[x]; + pix3 = (byte *)inRow2 + p1[x]; + pix4 = (byte *)inRow2 + p2[x]; + + ((byte *)(out+x))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0]) >> 2; + ((byte *)(out+x))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1]) >> 2; + ((byte *)(out+x))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2]) >> 2; + ((byte *)(out+x))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3]) >> 2; + } + } + } + + return scaledImage; +} + +/* +================= +GL_BoxFilter3x3 + +box filter 3x3 +================= +*/ +void GL_BoxFilter3x3( byte *out, const byte *in, int w, int h, int x, int y ) +{ + int r = 0, g = 0, b = 0, a = 0; + int count = 0, acount = 0; + int i, j, u, v; + const byte *pixel; + + for( i = 0; i < 3; i++ ) + { + u = ( i - 1 ) + x; + + for( j = 0; j < 3; j++ ) + { + v = ( j - 1 ) + y; + + if( u >= 0 && u < w && v >= 0 && v < h ) + { + pixel = &in[( u + v * w ) * 4]; + + if( pixel[3] != 0 ) + { + r += pixel[0]; + g += pixel[1]; + b += pixel[2]; + a += pixel[3]; + acount++; + } + } + } + } + + if( acount == 0 ) + acount = 1; + + out[0] = r / acount; + out[1] = g / acount; + out[2] = b / acount; +// out[3] = (int)( SimpleSpline( ( a / 12.0f ) / 255.0f ) * 255 ); +} + +/* +================= +GL_ApplyFilter + +Apply box-filter to 1-bit alpha +================= +*/ +byte *GL_ApplyFilter( const byte *source, int width, int height ) +{ + byte *in = (byte *)source; + byte *out = (byte *)source; + int i; + + if( gEngfuncs.Host_IsQuakeCompatible() ) + return in; + + for( i = 0; source && i < width * height; i++, in += 4 ) + { + if( in[0] == 0 && in[1] == 0 && in[2] == 0 && in[3] == 0 ) + GL_BoxFilter3x3( in, source, width, height, i % width, i / width ); + } + + return out; +} + +/* +================= +GL_BuildMipMap + +Operates in place, quartering the size of the texture +================= +*/ +static void GL_BuildMipMap( byte *in, int srcWidth, int srcHeight, int srcDepth, int flags ) +{ + byte *out = in; + int instride = ALIGN( srcWidth * 4, 1 ); + int mipWidth, mipHeight, outpadding; + int row, x, y, z; + vec3_t normal; + + if( !in ) return; + + mipWidth = Q_max( 1, ( srcWidth >> 1 )); + mipHeight = Q_max( 1, ( srcHeight >> 1 )); + outpadding = ALIGN( mipWidth * 4, 1 ) - mipWidth * 4; + row = srcWidth << 2; + + if( FBitSet( flags, TF_ALPHACONTRAST )) + { + memset( in, mipWidth, mipWidth * mipHeight * 4 ); + return; + } + + // move through all layers + for( z = 0; z < srcDepth; z++ ) + { + if( FBitSet( flags, TF_NORMALMAP )) + { + for( y = 0; y < mipHeight; y++, in += instride * 2, out += outpadding ) + { + byte *next = ((( y << 1 ) + 1 ) < srcHeight ) ? ( in + instride ) : in; + for( x = 0, row = 0; x < mipWidth; x++, row += 8, out += 4 ) + { + if((( x << 1 ) + 1 ) < srcWidth ) + { + normal[0] = MAKE_SIGNED( in[row+0] ) + MAKE_SIGNED( in[row+4] ) + + MAKE_SIGNED( next[row+0] ) + MAKE_SIGNED( next[row+4] ); + normal[1] = MAKE_SIGNED( in[row+1] ) + MAKE_SIGNED( in[row+5] ) + + MAKE_SIGNED( next[row+1] ) + MAKE_SIGNED( next[row+5] ); + normal[2] = MAKE_SIGNED( in[row+2] ) + MAKE_SIGNED( in[row+6] ) + + MAKE_SIGNED( next[row+2] ) + MAKE_SIGNED( next[row+6] ); + } + else + { + normal[0] = MAKE_SIGNED( in[row+0] ) + MAKE_SIGNED( next[row+0] ); + normal[1] = MAKE_SIGNED( in[row+1] ) + MAKE_SIGNED( next[row+1] ); + normal[2] = MAKE_SIGNED( in[row+2] ) + MAKE_SIGNED( next[row+2] ); + } + + if( !VectorNormalizeLength( normal )) + VectorSet( normal, 0.5f, 0.5f, 1.0f ); + + out[0] = 128 + (byte)(127.0f * normal[0]); + out[1] = 128 + (byte)(127.0f * normal[1]); + out[2] = 128 + (byte)(127.0f * normal[2]); + out[3] = 255; + } + } + } + else + { + for( y = 0; y < mipHeight; y++, in += instride * 2, out += outpadding ) + { + byte *next = ((( y << 1 ) + 1 ) < srcHeight ) ? ( in + instride ) : in; + for( x = 0, row = 0; x < mipWidth; x++, row += 8, out += 4 ) + { + if((( x << 1 ) + 1 ) < srcWidth ) + { + out[0] = (in[row+0] + in[row+4] + next[row+0] + next[row+4]) >> 2; + out[1] = (in[row+1] + in[row+5] + next[row+1] + next[row+5]) >> 2; + out[2] = (in[row+2] + in[row+6] + next[row+2] + next[row+6]) >> 2; + out[3] = (in[row+3] + in[row+7] + next[row+3] + next[row+7]) >> 2; + } + else + { + out[0] = (in[row+0] + next[row+0]) >> 1; + out[1] = (in[row+1] + next[row+1]) >> 1; + out[2] = (in[row+2] + next[row+2]) >> 1; + out[3] = (in[row+3] + next[row+3]) >> 1; + } + } + } + } + } +} + +/* +=============== +GL_UploadTexture + +upload texture into video memory +=============== +*/ +static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) +{ + byte *buf, *data; + size_t texsize, size; + uint width, height; + uint i, j, numSides; + uint offset = 0; + qboolean normalMap; + const byte *bufend; + + tex->fogParams[0] = pic->fogParams[0]; + tex->fogParams[1] = pic->fogParams[1]; + tex->fogParams[2] = pic->fogParams[2]; + tex->fogParams[3] = pic->fogParams[3]; + GL_SetTextureDimensions( tex, pic->width, pic->height, pic->depth ); + GL_SetTextureFormat( tex, pic->type, pic->flags ); + + gEngfuncs.Con_Printf("%s %d %d\n", tex->name, tex->width, tex->height ); + + if( !pic->buffer ) + return true; + + tex->pixels[0] = Mem_Calloc( r_temppool, tex->width * tex->height * sizeof(pixel_t) + 64 ); + for( i = 0; i < tex->width * tex->height; i++ ) + { + unsigned int r, g, b; + r = pic->buffer[i * 4 + 0] * BIT(5) / 256; + g = pic->buffer[i * 4 + 1] * BIT(6) / 256; + b = pic->buffer[i * 4 + 2] * BIT(5) / 256; + + /// TODO: use internal rgb565-based palette for textures and screen + tex->pixels[0][i] = r << (6 + 5) | (g << 5) | b; + } + +#if 0 + Assert( pic != NULL ); + Assert( tex != NULL ); + + GL_SetTextureTarget( tex, pic ); // must be first + + // make sure what target is correct + if( tex->target == GL_NONE ) + { + gEngfuncs.Con_DPrintf( S_ERROR "GL_UploadTexture: %s is not supported by your hardware\n", tex->name ); + return false; + } + + GL_SetTextureDimensions( tex, pic->width, pic->height, pic->depth ); + GL_SetTextureFormat( tex, pic->type, pic->flags ); + + tex->fogParams[0] = pic->fogParams[0]; + tex->fogParams[1] = pic->fogParams[1]; + tex->fogParams[2] = pic->fogParams[2]; + tex->fogParams[3] = pic->fogParams[3]; + + if(( pic->width * pic->height ) & 3 ) + { + // will be resampled, just tell me for debug targets + gEngfuncs.Con_Reportf( "GL_UploadTexture: %s s&3 [%d x %d]\n", tex->name, pic->width, pic->height ); + } + + buf = pic->buffer; + bufend = pic->buffer + pic->size; // total image size include all the layers, cube sides, mipmaps + offset = GL_CalcImageSize( pic->type, pic->width, pic->height, pic->depth ); + texsize = GL_CalcTextureSize( tex->format, tex->width, tex->height, tex->depth ); + normalMap = FBitSet( tex->flags, TF_NORMALMAP ) ? true : false; + numSides = FBitSet( pic->flags, IMAGE_CUBEMAP ) ? 6 : 1; + + // uploading texture into video memory, change the binding + glState.currentTextures[glState.activeTMU] = tex->texnum; + pglBindTexture( tex->target, tex->texnum ); + + for( i = 0; i < numSides; i++ ) + { + // track the buffer bounds + if( buf != NULL && buf >= bufend ) + gEngfuncs.Host_Error( "GL_UploadTexture: %s image buffer overflow\n", tex->name ); + + if( ImageDXT( pic->type )) + { + for( j = 0; j < Q_max( 1, pic->numMips ); j++ ) + { + width = Q_max( 1, ( tex->width >> j )); + height = Q_max( 1, ( tex->height >> j )); + texsize = GL_CalcTextureSize( tex->format, width, height, tex->depth ); + size = GL_CalcImageSize( pic->type, width, height, tex->depth ); + GL_TextureImageDXT( tex, i, j, width, height, tex->depth, size, buf ); + tex->size += texsize; + buf += size; // move pointer + tex->numMips++; + + GL_CheckTexImageError( tex ); + } + } + else if( Q_max( 1, pic->numMips ) > 1 ) // not-compressed DDS + { + for( j = 0; j < Q_max( 1, pic->numMips ); j++ ) + { + width = Q_max( 1, ( tex->width >> j )); + height = Q_max( 1, ( tex->height >> j )); + texsize = GL_CalcTextureSize( tex->format, width, height, tex->depth ); + size = GL_CalcImageSize( pic->type, width, height, tex->depth ); + GL_TextureImageRAW( tex, i, j, width, height, tex->depth, pic->type, buf ); + tex->size += texsize; + buf += size; // move pointer + tex->numMips++; + + GL_CheckTexImageError( tex ); + + } + } + else // RGBA32 + { + int mipCount = GL_CalcMipmapCount( tex, ( buf != NULL )); + + // NOTE: only single uncompressed textures can be resamples, no mips, no layers, no sides + if(( tex->depth == 1 ) && ( pic->width != tex->width ) || ( pic->height != tex->height )) + data = GL_ResampleTexture( buf, pic->width, pic->height, tex->width, tex->height, normalMap ); + else data = buf; + + if( !ImageDXT( pic->type ) && !FBitSet( tex->flags, TF_NOMIPMAP ) && FBitSet( pic->flags, IMAGE_ONEBIT_ALPHA )) + data = GL_ApplyFilter( data, tex->width, tex->height ); + + // mips will be auto-generated if desired + for( j = 0; j < mipCount; j++ ) + { + width = Q_max( 1, ( tex->width >> j )); + height = Q_max( 1, ( tex->height >> j )); + texsize = GL_CalcTextureSize( tex->format, width, height, tex->depth ); + size = GL_CalcImageSize( pic->type, width, height, tex->depth ); + GL_TextureImageRAW( tex, i, j, width, height, tex->depth, pic->type, data ); + if( mipCount > 1 ) + GL_BuildMipMap( data, width, height, tex->depth, tex->flags ); + tex->size += texsize; + tex->numMips++; + + GL_CheckTexImageError( tex ); + } + + // move to next side + if( numSides > 1 && ( buf != NULL )) + buf += GL_CalcImageSize( pic->type, pic->width, pic->height, 1 ); + } + } + + SetBits( tex->flags, TF_IMG_UPLOADED ); // done + tex->numMips /= numSides; + + return true; +#endif + return true; +} + +/* +=============== +GL_ProcessImage + +do specified actions on pixels +=============== +*/ +static void GL_ProcessImage( image_t *tex, rgbdata_t *pic ) +{ + uint img_flags = 0; + + // force upload texture as RGB or RGBA (detail textures requires this) + if( tex->flags & TF_FORCE_COLOR ) pic->flags |= IMAGE_HAS_COLOR; + if( pic->flags & IMAGE_HAS_ALPHA ) tex->flags |= TF_HAS_ALPHA; + + if( ImageDXT( pic->type )) + { + if( !pic->numMips ) + tex->flags |= TF_NOMIPMAP; // disable mipmapping by user request + + // clear all the unsupported flags + tex->flags &= ~TF_KEEP_SOURCE; + } + else + { + // copy flag about luma pixels + if( pic->flags & IMAGE_HAS_LUMA ) + tex->flags |= TF_HAS_LUMA; + + if( pic->flags & IMAGE_QUAKEPAL ) + tex->flags |= TF_QUAKEPAL; + + // create luma texture from quake texture + if( tex->flags & TF_MAKELUMA ) + { + img_flags |= IMAGE_MAKE_LUMA; + tex->flags &= ~TF_MAKELUMA; + } + + if( tex->flags & TF_ALLOW_EMBOSS ) + { + img_flags |= IMAGE_EMBOSS; + tex->flags &= ~TF_ALLOW_EMBOSS; + } + + if( !FBitSet( tex->flags, TF_IMG_UPLOADED ) && FBitSet( tex->flags, TF_KEEP_SOURCE )) + tex->original = gEngfuncs.FS_CopyImage( pic ); // because current pic will be expanded to rgba + + // we need to expand image into RGBA buffer + if( pic->type == PF_INDEXED_24 || pic->type == PF_INDEXED_32 ) + img_flags |= IMAGE_FORCE_RGBA; + + // processing image before uploading (force to rgba, make luma etc) + if( pic->buffer ) gEngfuncs.Image_Process( &pic, 0, 0, img_flags, gl_emboss_scale->value ); + + if( FBitSet( tex->flags, TF_LUMINANCE )) + ClearBits( pic->flags, IMAGE_HAS_COLOR ); + } +} + +/* +================ +GL_CheckTexName +================ +*/ +qboolean GL_CheckTexName( const char *name ) +{ + if( !COM_CheckString( name ) ) + return false; + + // because multi-layered textures can exceed name string + if( Q_strlen( name ) >= sizeof( r_images->name )) + { + gEngfuncs.Con_Printf( S_ERROR "LoadTexture: too long name %s (%d)\n", name, Q_strlen( name )); + return false; + } + + return true; +} + +/* +================ +GL_TextureForName +================ +*/ +static image_t *GL_TextureForName( const char *name ) +{ + image_t *tex; + uint hash; + + // find the texture in array + hash = gEngfuncs.COM_HashKey( name, TEXTURES_HASH_SIZE ); + + for( tex = r_imagesHashTable[hash]; tex != NULL; tex = tex->nextHash ) + { + if( !Q_stricmp( tex->name, name )) + return tex; + } + + return NULL; +} + +/* +================ +GL_AllocTexture +================ +*/ +static image_t *GL_AllocTexture( const char *name, texFlags_t flags ) +{ + image_t *tex; + uint i; + + // find a free texture_t slot + for( i = 0, tex = r_images; i < r_numImages; i++, tex++ ) + if( !tex->name[0] ) break; + + if( i == r_numImages ) + { + if( r_numImages == MAX_TEXTURES ) + gEngfuncs.Host_Error( "GL_AllocTexture: MAX_TEXTURES limit exceeds\n" ); + r_numImages++; + } + + tex = &r_images[i]; + + // copy initial params + Q_strncpy( tex->name, name, sizeof( tex->name )); + + //tex->texnum = i; // texnum is used for fast acess into gl_textures array too + tex->flags = flags; + + // add to hash table + tex->hashValue = gEngfuncs.COM_HashKey( name, TEXTURES_HASH_SIZE ); + tex->nextHash = r_imagesHashTable[tex->hashValue]; + r_imagesHashTable[tex->hashValue] = tex; + + return tex; +} + +/* +================ +GL_DeleteTexture +================ +*/ +static void GL_DeleteTexture( image_t *tex ) +{ + image_t **prev; + image_t *cur; + + ASSERT( tex != NULL ); + + // already freed? + if( !tex->pixels) return; + + // debug + if( !tex->name[0] ) + { + gEngfuncs.Con_Printf( S_ERROR "GL_DeleteTexture: trying to free unnamed texture\n"); + return; + } + + // remove from hash table + prev = &r_imagesHashTable[tex->hashValue]; + + while( 1 ) + { + cur = *prev; + if( !cur ) break; + + if( cur == tex ) + { + *prev = cur->nextHash; + break; + } + prev = &cur->nextHash; + } + + // release source + if( tex->original ) + gEngfuncs.FS_FreeImage( tex->original ); + + memset( tex, 0, sizeof( *tex )); +} + +/* +================ +GL_UpdateTexSize + +recalc image room +================ +*/ +void GL_UpdateTexSize( int texnum, int width, int height, int depth ) +{ + int i, j, texsize; + int numSides; + image_t *tex; + + if( texnum <= 0 || texnum >= MAX_TEXTURES ) + return; + + tex = &r_images[texnum]; + numSides = FBitSet( tex->flags, TF_CUBEMAP ) ? 6 : 1; + GL_SetTextureDimensions( tex, width, height, depth ); + tex->size = 0; // recompute now + + for( i = 0; i < numSides; i++ ) + { + for( j = 0; j < Q_max( 1, tex->numMips ); j++ ) + { + width = Q_max( 1, ( tex->width >> j )); + height = Q_max( 1, ( tex->height >> j )); + texsize = GL_CalcTextureSize( width, height, tex->depth ); + tex->size += texsize; + } + } +} + +/* +================ +GL_LoadTexture +================ +*/ +int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags ) +{ + image_t *tex; + rgbdata_t *pic; + uint picFlags = 0; + + if( !GL_CheckTexName( name )) + return 0; + + // see if already loaded + if(( tex = GL_TextureForName( name ))) + return (tex - r_images); + + if( FBitSet( flags, TF_NOFLIP_TGA )) + SetBits( picFlags, IL_DONTFLIP_TGA ); + + if( FBitSet( flags, TF_KEEP_SOURCE ) && !FBitSet( flags, TF_EXPAND_SOURCE )) + SetBits( picFlags, IL_KEEP_8BIT ); + + // set some image flags + gEngfuncs.Image_SetForceFlags( picFlags ); + + pic = gEngfuncs.FS_LoadImage( name, buf, size ); + if( !pic ) return 0; // couldn't loading image + + // allocate the new one + tex = GL_AllocTexture( name, flags ); + GL_ProcessImage( tex, pic ); + + if( !GL_UploadTexture( tex, pic )) + { + memset( tex, 0, sizeof( image_t )); + gEngfuncs.FS_FreeImage( pic ); // release source texture + return 0; + } + + GL_ApplyTextureParams( tex ); // update texture filter, wrap etc + gEngfuncs.FS_FreeImage( pic ); // release source texture + + // NOTE: always return texnum as index in array or engine will stop work !!! + return tex - r_images; +} + +/* +================ +GL_LoadTextureArray +================ +*/ +int GL_LoadTextureArray( const char **names, int flags ) +{ + return 0; +} + +/* +================ +GL_LoadTextureFromBuffer +================ +*/ +int GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update ) +{ + image_t *tex; + + if( !GL_CheckTexName( name )) + return 0; + + // see if already loaded + if(( tex = GL_TextureForName( name )) && !update ) + return (tex - r_images); + + // couldn't loading image + if( !pic ) return 0; + + if( update ) + { + if( tex == NULL ) + gEngfuncs.Host_Error( "GL_LoadTextureFromBuffer: couldn't find texture %s for update\n", name ); + SetBits( tex->flags, flags ); + } + else + { + // allocate the new one + tex = GL_AllocTexture( name, flags ); + } + + GL_ProcessImage( tex, pic ); + if( !GL_UploadTexture( tex, pic )) + { + memset( tex, 0, sizeof( image_t )); + return 0; + } + + GL_ApplyTextureParams( tex ); // update texture filter, wrap etc + return (tex - r_images); +} + +/* +================ +GL_CreateTexture + +creates texture from buffer +================ +*/ +int GL_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags ) +{ + int datasize = 1; + rgbdata_t r_empty; + + if( FBitSet( flags, TF_ARB_16BIT )) + datasize = 2; + else if( FBitSet( flags, TF_ARB_FLOAT )) + datasize = 4; + + memset( &r_empty, 0, sizeof( r_empty )); + r_empty.width = width; + r_empty.height = height; + r_empty.type = PF_RGBA_32; + r_empty.size = r_empty.width * r_empty.height * datasize * 4; + r_empty.buffer = (byte *)buffer; + + // clear invalid combinations + ClearBits( flags, TF_TEXTURE_3D ); + + // if image not luminance and not alphacontrast it will have color + if( !FBitSet( flags, TF_LUMINANCE ) && !FBitSet( flags, TF_ALPHACONTRAST )) + SetBits( r_empty.flags, IMAGE_HAS_COLOR ); + + if( FBitSet( flags, TF_HAS_ALPHA )) + SetBits( r_empty.flags, IMAGE_HAS_ALPHA ); + + if( FBitSet( flags, TF_CUBEMAP )) + { + return 0; + } + + return GL_LoadTextureInternal( name, &r_empty, flags ); +} + +/* +================ +GL_CreateTextureArray + +creates texture array from buffer +================ +*/ +int GL_CreateTextureArray( const char *name, int width, int height, int depth, const void *buffer, texFlags_t flags ) +{ + return 0; +} + +/* +================ +GL_FindTexture +================ +*/ +int GL_FindTexture( const char *name ) +{ + image_t *tex; + + if( !GL_CheckTexName( name )) + return 0; + + // see if already loaded + if(( tex = GL_TextureForName( name ))) + return (tex - r_images); + + return 0; +} + +/* +================ +GL_FreeTexture +================ +*/ +void GL_FreeTexture( unsigned int texnum ) +{ + // number 0 it's already freed + if( texnum <= 0 ) + return; + + GL_DeleteTexture( &r_images[texnum] ); +} + +/* +================ +GL_ProcessTexture +================ +*/ +void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor ) +{ + image_t *image; + rgbdata_t *pic; + int flags = 0; + + if( texnum <= 0 || texnum >= MAX_TEXTURES ) + return; // missed image + image = &r_images[texnum]; + + // select mode + if( gamma != -1.0f ) + { + flags = IMAGE_LIGHTGAMMA; + } + else if( topColor != -1 && bottomColor != -1 ) + { + flags = IMAGE_REMAP; + } + else + { + gEngfuncs.Con_Printf( S_ERROR "GL_ProcessTexture: bad operation for %s\n", image->name ); + return; + } + + if( !image->original ) + { + gEngfuncs.Con_Printf( S_ERROR "GL_ProcessTexture: no input data for %s\n", image->name ); + return; + } + + if( ImageDXT( image->original->type )) + { + gEngfuncs.Con_Printf( S_ERROR "GL_ProcessTexture: can't process compressed texture %s\n", image->name ); + return; + } + + // all the operations makes over the image copy not an original + pic = gEngfuncs.FS_CopyImage( image->original ); + gEngfuncs.Image_Process( &pic, topColor, bottomColor, flags, 0.0f ); + + GL_UploadTexture( image, pic ); + GL_ApplyTextureParams( image ); // update texture filter, wrap etc + + gEngfuncs.FS_FreeImage( pic ); +} + +/* +============================================================================== + +INTERNAL TEXTURES + +============================================================================== +*/ +/* +================== +GL_FakeImage +================== +*/ +static rgbdata_t *GL_FakeImage( int width, int height, int depth, int flags ) +{ + static byte data2D[1024]; // 16x16x4 + static rgbdata_t r_image; + + // also use this for bad textures, but without alpha + r_image.width = Q_max( 1, width ); + r_image.height = Q_max( 1, height ); + r_image.depth = Q_max( 1, depth ); + r_image.flags = flags; + r_image.type = PF_RGBA_32; + r_image.size = r_image.width * r_image.height * r_image.depth * 4; + r_image.buffer = (r_image.size > sizeof( data2D )) ? NULL : data2D; + r_image.palette = NULL; + r_image.numMips = 1; + r_image.encode = 0; + + if( FBitSet( r_image.flags, IMAGE_CUBEMAP )) + r_image.size *= 6; + memset( data2D, 0xFF, sizeof( data2D )); + + return &r_image; +} + +/* +================== +R_InitDlightTexture +================== +*/ +void R_InitDlightTexture( void ) +{ + rgbdata_t r_image; + + if( tr.dlightTexture != 0 ) + return; // already initialized + + memset( &r_image, 0, sizeof( r_image )); + r_image.width = BLOCK_SIZE; + r_image.height = BLOCK_SIZE; + r_image.flags = IMAGE_HAS_COLOR; + r_image.type = PF_RGBA_32; + r_image.size = r_image.width * r_image.height * 4; + + tr.dlightTexture = GL_LoadTextureInternal( "*dlight", &r_image, TF_NOMIPMAP|TF_CLAMP|TF_ATLAS_PAGE ); +} + +/* +================== +GL_CreateInternalTextures +================== +*/ +static void GL_CreateInternalTextures( void ) +{ + int dx2, dy, d; + int x, y; + rgbdata_t *pic; + + // emo-texture from quake1 + pic = GL_FakeImage( 16, 16, 1, IMAGE_HAS_COLOR ); + + for( y = 0; y < 16; y++ ) + { + for( x = 0; x < 16; x++ ) + { + if(( y < 8 ) ^ ( x < 8 )) + ((uint *)pic->buffer)[y*16+x] = 0xFFFF00FF; + else ((uint *)pic->buffer)[y*16+x] = 0xFF000000; + } + } + + tr.defaultTexture = GL_LoadTextureInternal( "*default", pic, TF_COLORMAP ); + + // particle texture from quake1 + pic = GL_FakeImage( 16, 16, 1, IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA ); + + for( x = 0; x < 16; x++ ) + { + dx2 = x - 8; + dx2 = dx2 * dx2; + + for( y = 0; y < 16; y++ ) + { + dy = y - 8; + d = 255 - 35 * sqrt( dx2 + dy * dy ); + pic->buffer[( y * 16 + x ) * 4 + 3] = bound( 0, d, 255 ); + } + } + + tr.particleTexture = GL_LoadTextureInternal( "*particle", pic, TF_CLAMP ); + + // white texture + pic = GL_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR ); + for( x = 0; x < 16; x++ ) + ((uint *)pic->buffer)[x] = 0xFFFFFFFF; + tr.whiteTexture = GL_LoadTextureInternal( "*white", pic, TF_COLORMAP ); + + // gray texture + pic = GL_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR ); + for( x = 0; x < 16; x++ ) + ((uint *)pic->buffer)[x] = 0xFF7F7F7F; + tr.grayTexture = GL_LoadTextureInternal( "*gray", pic, TF_COLORMAP ); + + // black texture + pic = GL_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR ); + for( x = 0; x < 16; x++ ) + ((uint *)pic->buffer)[x] = 0xFF000000; + tr.blackTexture = GL_LoadTextureInternal( "*black", pic, TF_COLORMAP ); + + // cinematic dummy + pic = GL_FakeImage( 640, 100, 1, IMAGE_HAS_COLOR ); + tr.cinTexture = GL_LoadTextureInternal( "*cintexture", pic, TF_NOMIPMAP|TF_CLAMP ); +} + +/* +=============== +R_TextureList_f +=============== +*/ +void R_TextureList_f( void ) +{ + image_t *image; + int i, texCount, bytes = 0; + + gEngfuncs.Con_Printf( "\n" ); + gEngfuncs.Con_Printf( " -id- -w- -h- -size- -fmt- -type- -data- -encode- -wrap- -depth- -name--------\n" ); + + for( i = texCount = 0, image = r_images; i < r_numImages; i++, image++ ) + { + if( !image->pixels ) continue; + + bytes += image->size; + texCount++; + + gEngfuncs.Con_Printf( "%4i: ", i ); + gEngfuncs.Con_Printf( "%4i %4i ", image->width, image->height ); + gEngfuncs.Con_Printf( "%12s ", Q_memprint( image->size )); + + if( image->flags & TF_NORMALMAP ) + gEngfuncs.Con_Printf( "normal " ); + else gEngfuncs.Con_Printf( "diffuse " ); + + if( image->flags & TF_CLAMP ) + gEngfuncs.Con_Printf( "clamp " ); + else if( image->flags & TF_BORDER ) + gEngfuncs.Con_Printf( "border " ); + else gEngfuncs.Con_Printf( "repeat " ); + gEngfuncs.Con_Printf( " %d ", image->depth ); + gEngfuncs.Con_Printf( " %s\n", image->name ); + } + + gEngfuncs.Con_Printf( "---------------------------------------------------------\n" ); + gEngfuncs.Con_Printf( "%i total textures\n", texCount ); + gEngfuncs.Con_Printf( "%s total memory used\n", Q_memprint( bytes )); + gEngfuncs.Con_Printf( "\n" ); +} + +/* +=============== +R_InitImages +=============== +*/ +void R_InitImages( void ) +{ + memset( r_images, 0, sizeof( r_images )); + memset( r_imagesHashTable, 0, sizeof( r_imagesHashTable )); + r_numImages = 0; + + // create unused 0-entry + Q_strncpy( r_images->name, "*unused*", sizeof( r_images->name )); + r_images->hashValue = gEngfuncs.COM_HashKey( r_images->name, TEXTURES_HASH_SIZE ); + r_images->nextHash = r_imagesHashTable[r_images->hashValue]; + r_imagesHashTable[r_images->hashValue] = r_images; + r_numImages = 1; + + // validate cvars + R_SetTextureParameters(); + GL_CreateInternalTextures(); + + gEngfuncs.Cmd_AddCommand( "texturelist", R_TextureList_f, "display loaded textures list" ); +} + +/* +=============== +R_ShutdownImages +=============== +*/ +void R_ShutdownImages( void ) +{ + image_t *tex; + int i; + + gEngfuncs.Cmd_RemoveCommand( "texturelist" ); + + for( i = 0, tex = r_images; i < r_numImages; i++, tex++ ) + GL_DeleteTexture( tex ); + + memset( tr.lightmapTextures, 0, sizeof( tr.lightmapTextures )); + memset( r_imagesHashTable, 0, sizeof( r_imagesHashTable )); + memset( r_images, 0, sizeof( r_images )); + r_numImages = 0; +} diff --git a/r_local.h b/r_local.h new file mode 100644 index 00000000..62b7a668 --- /dev/null +++ b/r_local.h @@ -0,0 +1,710 @@ +/* +gl_local.h - renderer local declarations +Copyright (C) 2010 Uncle Mike + +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 3 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. +*/ + +#ifndef GL_LOCAL_H +#define GL_LOCAL_H +#include "port.h" +#include "xash3d_types.h" +#include "cvardef.h" +#include "const.h" +#include "com_model.h" +#include "cl_entity.h" +#include "render_api.h" +#include "protocol.h" +#include "dlight.h" +#include "ref_api.h" +#include "mathlib.h" +#include "ref_params.h" +#include "enginefeatures.h" +#include "com_strings.h" +#include "pm_movevars.h" +//#include "cvar.h" +typedef struct mip_s mip_t; +#define offsetof(s,m) (size_t)&(((s *)0)->m) + +#define ASSERT(x) if(!( x )) gEngfuncs.Host_Error( "assert failed at %s:%i\n", __FILE__, __LINE__ ) +#define Assert(x) if(!( x )) gEngfuncs.Host_Error( "assert failed at %s:%i\n", __FILE__, __LINE__ ) + +#include + +#define CVAR_DEFINE( cv, cvname, cvstr, cvflags, cvdesc ) cvar_t cv = { cvname, cvstr, cvflags, 0.0f, (void *)CVAR_SENTINEL, cvdesc } +#define CVAR_DEFINE_AUTO( cv, cvstr, cvflags, cvdesc ) cvar_t cv = { #cv, cvstr, cvflags, 0.0f, (void *)CVAR_SENTINEL, cvdesc } +#define CVAR_TO_BOOL( x ) ((x) && ((x)->value != 0.0f) ? true : false ) + +#define WORLD (gEngfuncs.GetWorld()) +#define WORLDMODEL (gEngfuncs.pfnGetModelByIndex( 1 )) +#define MOVEVARS (gEngfuncs.pfnGetMoveVars()) + +// make mod_ref.h? +#define LM_SAMPLE_SIZE 16 + + +extern byte *r_temppool; + +#define BLOCK_SIZE tr.block_size // lightmap blocksize +#define BLOCK_SIZE_DEFAULT 128 // for keep backward compatibility +#define BLOCK_SIZE_MAX 1024 + +#define MAX_TEXTURES 4096 +#define MAX_DETAIL_TEXTURES 256 +#define MAX_LIGHTMAPS 256 +#define SUBDIVIDE_SIZE 64 +#define MAX_DECAL_SURFS 4096 +#define MAX_DRAW_STACK 2 // normal view and menu view + +#define SHADEDOT_QUANT 16 // precalculated dot products for quantized angles +#define SHADE_LAMBERT 1.495f +#define DEFAULT_ALPHATEST 0.0f + +// refparams +#define RP_NONE 0 +#define RP_ENVVIEW BIT( 0 ) // used for cubemapshot +#define RP_OLDVIEWLEAF BIT( 1 ) +#define RP_CLIPPLANE BIT( 2 ) + +#define RP_NONVIEWERREF (RP_ENVVIEW) +#define R_ModelOpaque( rm ) ( rm == kRenderNormal ) +#define R_StaticEntity( ent ) ( VectorIsNull( ent->origin ) && VectorIsNull( ent->angles )) +#define RP_LOCALCLIENT( e ) ((e) != NULL && (e)->index == gEngfuncs.GetPlayerIndex() && e->player ) +#define RP_NORMALPASS() ( FBitSet( RI.params, RP_NONVIEWERREF ) == 0 ) + +#define CL_IsViewEntityLocalPlayer() ( gEngfuncs.GetViewEntIndex() == gEngfuncs.GetPlayerIndex() ) + +#define CULL_VISIBLE 0 // not culled +#define CULL_BACKSIDE 1 // backside of transparent wall +#define CULL_FRUSTUM 2 // culled by frustum +#define CULL_VISFRAME 3 // culled by PVS +#define CULL_OTHER 4 // culled by other reason + + +/* + skins will be outline flood filled and mip mapped + pics and sprites with alpha will be outline flood filled + pic won't be mip mapped + model skin + sprite frame + wall texture + pic +*/ + +typedef enum +{ + it_skin, + it_sprite, + it_wall, + it_pic, + it_sky +} imagetype_t; + + +//=================================================================== + +typedef unsigned short pixel_t; + +typedef struct vrect_s +{ + int x,y,width,height; + struct vrect_s *pnext; +} vrect_t; + +typedef struct +{ + pixel_t *buffer; // invisible buffer + pixel_t *colormap; // 256 * VID_GRADES size + pixel_t *alphamap; // 256 * 256 translucency map + int rowbytes; // may be > width if displayed in a window + // can be negative for stupid dibs + int width; + int height; +} viddef_t; + +extern viddef_t vid; + +typedef struct +{ + int params; // rendering parameters + + qboolean drawWorld; // ignore world for drawing PlayerModel + qboolean isSkyVisible; // sky is visible + qboolean onlyClientDraw; // disabled by client request + qboolean drawOrtho; // draw world as orthogonal projection + + float fov_x, fov_y; // current view fov + + cl_entity_t *currententity; + model_t *currentmodel; + cl_entity_t *currentbeam; // same as above but for beams + + int viewport[4]; + //gl_frustum_t frustum; + + mleaf_t *viewleaf; + mleaf_t *oldviewleaf; + vec3_t pvsorigin; + vec3_t vieworg; // locked vieworigin + vec3_t viewangles; + vec3_t vforward; + vec3_t vright; + vec3_t vup; + + vec3_t cullorigin; + vec3_t cull_vforward; + vec3_t cull_vright; + vec3_t cull_vup; + + float farClip; + + qboolean fogCustom; + qboolean fogEnabled; + qboolean fogSkybox; + vec4_t fogColor; + float fogDensity; + float fogStart; + float fogEnd; + int cached_contents; // in water + int cached_waterlevel; // was in water + + float skyMins[2][6]; + float skyMaxs[2][6]; + + matrix4x4 objectMatrix; // currententity matrix + matrix4x4 worldviewMatrix; // modelview for world + matrix4x4 modelviewMatrix; // worldviewMatrix * objectMatrix + + matrix4x4 projectionMatrix; + matrix4x4 worldviewProjectionMatrix; // worldviewMatrix * projectionMatrix + byte visbytes[(MAX_MAP_LEAFS+7)/8];// actual PVS for current frame + + float viewplanedist; + mplane_t clipPlane; +} ref_instance_t; + +typedef struct +{ + cl_entity_t *solid_entities[MAX_VISIBLE_PACKET]; // opaque moving or alpha brushes + cl_entity_t *trans_entities[MAX_VISIBLE_PACKET]; // translucent brushes + cl_entity_t *beam_entities[MAX_VISIBLE_PACKET]; + uint num_solid_entities; + uint num_trans_entities; + uint num_beam_entities; +} draw_list_t; + +typedef struct +{ + int defaultTexture; // use for bad textures + int particleTexture; + int whiteTexture; + int grayTexture; + int blackTexture; + int solidskyTexture; // quake1 solid-sky layer + int alphaskyTexture; // quake1 alpha-sky layer + int lightmapTextures[MAX_LIGHTMAPS]; + int dlightTexture; // custom dlight texture + int skyboxTextures[6]; // skybox sides + int cinTexture; // cinematic texture + + int skytexturenum; // this not a gl_texturenum! + int skyboxbasenum; // start with 5800 + + // entity lists + draw_list_t draw_stack[MAX_DRAW_STACK]; + int draw_stack_pos; + draw_list_t *draw_list; + + msurface_t *draw_decals[MAX_DECAL_SURFS]; + int num_draw_decals; + + // OpenGL matrix states + qboolean modelviewIdentity; + + int visframecount; // PVS frame + int dlightframecount; // dynamic light frame + int realframecount; // not including viewpasses + int framecount; + + qboolean ignore_lightgamma; + qboolean fCustomRendering; + qboolean fResetVis; + qboolean fFlipViewModel; + + // tree visualization stuff + int recursion_level; + int max_recursion; + + byte visbytes[(MAX_MAP_LEAFS+7)/8]; // member custom PVS + int lightstylevalue[MAX_LIGHTSTYLES]; // value 0 - 65536 + int block_size; // lightmap blocksize + + double frametime; // special frametime for multipass rendering (will set to 0 on a nextview) + float blend; // global blend value + + // cull info + vec3_t modelorg; // relative to viewpoint + + qboolean fCustomSkybox; +} gl_globals_t; + +typedef struct +{ + uint c_world_polys; + uint c_studio_polys; + uint c_sprite_polys; + uint c_alias_polys; + uint c_world_leafs; + + uint c_view_beams_count; + uint c_active_tents_count; + uint c_alias_models_drawn; + uint c_studio_models_drawn; + uint c_sprite_models_drawn; + uint c_particle_count; + + uint c_client_ents; // entities that moved to client + double t_world_node; + double t_world_draw; +} ref_speeds_t; + +extern ref_speeds_t r_stats; +extern ref_instance_t RI; +extern gl_globals_t tr; + +extern float gldepthmin, gldepthmax; +#define r_numEntities (tr.draw_list->num_solid_entities + tr.draw_list->num_trans_entities) +#define r_numStatics (r_stats.c_client_ents) + +typedef struct image_s +{ + char name[256]; // game path, including extension (can be store image programs) + word srcWidth; // keep unscaled sizes + word srcHeight; + word width; // upload width\height + word height; + word depth; // texture depth or count of layers for 2D_ARRAY + byte numMips; // mipmap count + + + texFlags_t flags; + + rgba_t fogParams; // some water textures + // contain info about underwater fog + rgbdata_t *original; // keep original image + + // debug info + size_t size; // upload size for debug targets + + // detail textures stuff + float xscale; + float yscale; + + imagetype_t type; + qboolean transparent; + pixel_t *pixels[4]; // mip levels + + int servercount; + uint hashValue; + struct gltexture_s *nextHash; +} image_t; + +#if 0 + +// +// gl_backend.c +// +void GL_BackendStartFrame( void ); +void GL_BackendEndFrame( void ); +void GL_CleanUpTextureUnits( int last ); +void GL_Bind( int tmu, unsigned int texnum ); +void GL_LoadTexMatrix( const matrix4x4 m ); +void GL_LoadTexMatrixExt( const float *glmatrix ); +void GL_LoadMatrix( const matrix4x4 source ); +void GL_TexGen( unsigned int coord, unsigned int mode ); +void GL_SelectTexture( int texture ); +void GL_CleanupAllTextureUnits( void ); +void GL_LoadIdentityTexMatrix( void ); +void GL_DisableAllTexGens( void ); +void GL_SetRenderMode( int mode ); +void GL_TextureTarget( uint target ); +void GL_Cull( unsigned int cull ); +void R_ShowTextures( void ); +void R_ShowTree( void ); +void SCR_TimeRefresh_f( void ); + +// +// gl_beams.c +// +void CL_DrawBeams( int fTrans, BEAM *active_beams ); +qboolean R_BeamCull( const vec3_t start, const vec3_t end, qboolean pvsOnly ); + +// +// gl_cull.c +// +int R_CullModel( cl_entity_t *e, const vec3_t absmin, const vec3_t absmax ); +qboolean R_CullBox( const vec3_t mins, const vec3_t maxs ); +qboolean R_CullSphere( const vec3_t centre, const float radius ); +//int R_CullSurface( msurface_t *surf, gl_frustum_t *frustum, uint clipflags ); + +// +// gl_decals.c +// +void DrawSurfaceDecals( msurface_t *fa, qboolean single, qboolean reverse ); +float *R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, int texture, int *outCount ); +void DrawSingleDecal( decal_t *pDecal, msurface_t *fa ); +void R_EntityRemoveDecals( model_t *mod ); +void DrawDecalsBatch( void ); +void R_ClearDecals( void ); + + + +// +// gl_drawhulls.c +// +void R_DrawWorldHull( void ); +void R_DrawModelHull( void ); +#endif + +void GL_Bind( int tmu, unsigned int texnum ); + +// +// gl_draw.c +// +void R_Set2DMode( qboolean enable ); +void R_DrawTileClear( int texnum, int x, int y, int w, int h ); +void R_UploadStretchRaw( int texture, int cols, int rows, int width, int height, const byte *data );// + +// gl_image.c +// +void R_SetTextureParameters( void ); +image_t *R_GetTexture( unsigned int texnum ); +#define GL_LoadTextureInternal( name, pic, flags ) GL_LoadTextureFromBuffer( name, pic, flags, false ) +#define GL_UpdateTextureInternal( name, pic, flags ) GL_LoadTextureFromBuffer( name, pic, flags, true ) +int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags ); +int GL_LoadTextureArray( const char **names, int flags ); +int GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update ); +byte *GL_ResampleTexture( const byte *source, int in_w, int in_h, int out_w, int out_h, qboolean isNormalMap ); +int GL_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags ); +int GL_CreateTextureArray( const char *name, int width, int height, int depth, const void *buffer, texFlags_t flags ); +void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor ); +void GL_UpdateTexSize( int texnum, int width, int height, int depth ); +void GL_ApplyTextureParams( image_t *tex ); +int GL_FindTexture( const char *name ); +void GL_FreeTexture( unsigned int texnum ); +const char *GL_Target( unsigned int target ); +void R_InitDlightTexture( void ); +void R_TextureList_f( void ); +void R_InitImages( void ); +void R_ShutdownImages( void ); +#if 0 +// +// gl_rlight.c +// +void CL_RunLightStyles( void ); +void R_PushDlights( void ); +void R_AnimateLight( void ); +void R_GetLightSpot( vec3_t lightspot ); +void R_MarkLights( dlight_t *light, int bit, mnode_t *node ); +colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lightspot, vec3_t lightvec ); +int R_CountSurfaceDlights( msurface_t *surf ); +colorVec R_LightPoint( const vec3_t p0 ); +int R_CountDlights( void ); + +// +// gl_rmain.c +// +void R_ClearScene( void ); +void R_LoadIdentity( void ); +void R_RenderScene( void ); +void R_DrawCubemapView( const vec3_t origin, const vec3_t angles, int size ); +void R_SetupRefParams( const struct ref_viewpass_s *rvp ); +void R_TranslateForEntity( cl_entity_t *e ); +void R_RotateForEntity( cl_entity_t *e ); +void R_SetupGL( qboolean set_gl_state ); +void R_AllowFog( qboolean allowed ); +void R_SetupFrustum( void ); +void R_FindViewLeaf( void ); +void R_PushScene( void ); +void R_PopScene( void ); +void R_DrawFog( void ); + +// +// gl_rmath.c +// +void Matrix4x4_ToArrayFloatGL( const matrix4x4 in, float out[16] ); +void Matrix4x4_FromArrayFloatGL( matrix4x4 out, const float in[16] ); +void Matrix4x4_Concat( matrix4x4 out, const matrix4x4 in1, const matrix4x4 in2 ); +void Matrix4x4_ConcatTranslate( matrix4x4 out, float x, float y, float z ); +void Matrix4x4_ConcatRotate( matrix4x4 out, float angle, float x, float y, float z ); +void Matrix4x4_ConcatScale( matrix4x4 out, float x ); +void Matrix4x4_ConcatScale3( matrix4x4 out, float x, float y, float z ); +void Matrix4x4_CreateTranslate( matrix4x4 out, float x, float y, float z ); +void Matrix4x4_CreateRotate( matrix4x4 out, float angle, float x, float y, float z ); +void Matrix4x4_CreateScale( matrix4x4 out, float x ); +void Matrix4x4_CreateScale3( matrix4x4 out, float x, float y, float z ); +void Matrix4x4_CreateProjection(matrix4x4 out, float xMax, float xMin, float yMax, float yMin, float zNear, float zFar); +void Matrix4x4_CreateOrtho(matrix4x4 m, float xLeft, float xRight, float yBottom, float yTop, float zNear, float zFar); +void Matrix4x4_CreateModelview( matrix4x4 out ); + +// +// gl_rmisc.c +// +void R_ClearStaticEntities( void ); + +// +// gl_rsurf.c +// +void R_MarkLeaves( void ); +void R_DrawWorld( void ); +void R_DrawWaterSurfaces( void ); +void R_DrawBrushModel( cl_entity_t *e ); +void GL_SubdivideSurface( msurface_t *fa ); +void GL_BuildPolygonFromSurface( model_t *mod, msurface_t *fa ); +void DrawGLPoly( glpoly_t *p, float xScale, float yScale ); +texture_t *R_TextureAnimation( msurface_t *s ); +void GL_SetupFogColorForSurfaces( void ); +void R_DrawAlphaTextureChains( void ); +void GL_RebuildLightmaps( void ); +void GL_InitRandomTable( void ); +void GL_BuildLightmaps( void ); +void GL_ResetFogColor( void ); +void R_GenerateVBO(); +void R_ClearVBO(); +void R_AddDecalVBO( decal_t *pdecal, msurface_t *surf ); + +// +// gl_rpart.c +// +void CL_DrawParticlesExternal( const ref_viewpass_t *rvp, qboolean trans_pass, float frametime ); +void CL_DrawParticles( double frametime, particle_t *cl_active_particles, float partsize ); +void CL_DrawTracers( double frametime, particle_t *cl_active_tracers ); + + +// +// gl_sprite.c +// +void R_SpriteInit( void ); +void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags ); +mspriteframe_t *R_GetSpriteFrame( const model_t *pModel, int frame, float yaw ); +void R_DrawSpriteModel( cl_entity_t *e ); + +// +// gl_studio.c +// +void R_StudioInit( void ); +void Mod_LoadStudioModel( model_t *mod, const void *buffer, qboolean *loaded ); +void R_StudioLerpMovement( cl_entity_t *e, double time, vec3_t origin, vec3_t angles ); +float CL_GetSequenceDuration( cl_entity_t *ent, int sequence ); +struct mstudiotex_s *R_StudioGetTexture( cl_entity_t *e ); +float CL_GetStudioEstimatedFrame( cl_entity_t *ent ); +int R_GetEntityRenderMode( cl_entity_t *ent ); +void R_DrawStudioModel( cl_entity_t *e ); +player_info_t *pfnPlayerInfo( int index ); +void R_GatherPlayerLight( void ); +float R_StudioEstimateFrame( cl_entity_t *e, mstudioseqdesc_t *pseqdesc ); +void R_StudioLerpMovement( cl_entity_t *e, double time, vec3_t origin, vec3_t angles ); +void R_StudioResetPlayerModels( void ); +void CL_InitStudioAPI( void ); +void Mod_StudioLoadTextures( model_t *mod, void *data ); +void Mod_StudioUnloadTextures( void *data ); + +// +// gl_alias.c +// +void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded ); +void R_DrawAliasModel( cl_entity_t *e ); +void R_AliasInit( void ); + +// +// gl_warp.c +// + +void R_InitSkyClouds( mip_t *mt, struct texture_s *tx, qboolean custom_palette ); +void R_AddSkyBoxSurface( msurface_t *fa ); +void R_ClearSkyBox( void ); +void R_DrawSkyBox( void ); +void R_DrawClouds( void ); +void EmitWaterPolys( msurface_t *warp, qboolean reverse ); +#endif + +void R_InitSkyClouds( struct mip_s *mt, struct texture_s *tx, qboolean custom_palette ); +// +// gl_vgui.c +// +void VGUI_DrawInit( void ); +void VGUI_DrawShutdown( void ); +void VGUI_SetupDrawingText( int *pColor ); +void VGUI_SetupDrawingRect( int *pColor ); +void VGUI_SetupDrawingImage( int *pColor ); +void VGUI_BindTexture( int id ); +void VGUI_EnableTexture( qboolean enable ); +void VGUI_CreateTexture( int id, int width, int height ); +void VGUI_UploadTexture( int id, const char *buffer, int width, int height ); +void VGUI_UploadTextureBlock( int id, int drawX, int drawY, const byte *rgba, int blockWidth, int blockHeight ); +void VGUI_DrawQuad( const vpoint_t *ul, const vpoint_t *lr ); +void VGUI_GetTextureSizes( int *width, int *height ); +int VGUI_GenerateTexture( void ); + +//#include "vid_common.h" + +// +// renderer exports +// +qboolean R_Init( void ); +void R_Shutdown( void ); +void GL_SetupAttributes( int safegl ); +void GL_OnContextCreated( void ); +void GL_InitExtensions( void ); +void GL_ClearExtensions( void ); +void VID_CheckChanges( void ); +int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags ); +void GL_FreeImage( const char *name ); +qboolean VID_ScreenShot( const char *filename, int shot_type ); +qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qboolean skyshot ); +void R_BeginFrame( qboolean clearScene ); +int R_RenderFrame( const struct ref_viewpass_s *vp ); +void R_EndFrame( void ); +void R_ClearScene( void ); +void R_GetTextureParms( int *w, int *h, int texnum ); +void R_GetSpriteParms( int *frameWidth, int *frameHeight, int *numFrames, int curFrame, const struct model_s *pSprite ); +void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean dirty ); +void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum ); +qboolean R_SpeedsMessage( char *out, size_t size ); +void R_SetupSky( const char *skyboxname ); +qboolean R_CullBox( const vec3_t mins, const vec3_t maxs ); +int R_WorldToScreen( const vec3_t point, vec3_t screen ); +void R_ScreenToWorld( const vec3_t screen, vec3_t point ); +qboolean R_AddEntity( struct cl_entity_s *pRefEntity, int entityType ); +void Mod_LoadMapSprite( struct model_s *mod, const void *buffer, size_t size, qboolean *loaded ); +void Mod_SpriteUnloadTextures( void *data ); +void Mod_UnloadAliasModel( struct model_s *mod ); +void Mod_AliasUnloadTextures( void *data ); +void GL_SetRenderMode( int mode ); +void R_RunViewmodelEvents( void ); +void R_DrawViewModel( void ); +int R_GetSpriteTexture( const struct model_s *m_pSpriteModel, int frame ); +void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale ); +void R_RemoveEfrags( struct cl_entity_s *ent ); +void R_AddEfrags( struct cl_entity_s *ent ); +void R_DecalRemoveAll( int texture ); +int R_CreateDecalList( decallist_t *pList ); +void R_ClearAllDecals( void ); +byte *Mod_GetCurrentVis( void ); +void Mod_SetOrthoBounds( const float *mins, const float *maxs ); +void R_NewMap( void ); +void CL_AddCustomBeam( cl_entity_t *pEnvBeam ); +#if 0 +// +// gl_opengl.c +// +#define GL_CheckForErrors() GL_CheckForErrors_( __FILE__, __LINE__ ) +void GL_CheckForErrors_( const char *filename, const int fileline ); +const char *GL_ErrorString( int err ); +qboolean GL_Support( int r_ext ); +int GL_MaxTextureUnits( void ); +void GL_CheckExtension( const char *name, const dllfunc_t *funcs, const char *cvarname, int r_ext ); +void GL_SetExtension( int r_ext, int enable ); +#endif +// +// gl_triapi.c +// +void TriRenderMode( int mode ); +void TriBegin( int mode ); +void TriEnd( void ); +void TriTexCoord2f( float u, float v ); +void TriVertex3fv( const float *v ); +void TriVertex3f( float x, float y, float z ); +void _TriColor4f( float r, float g, float b, float a ); +void TriColor4ub( byte r, byte g, byte b, byte a ); +int TriWorldToScreen( float *world, float *screen ); +int TriSpriteTexture( model_t *pSpriteModel, int frame ); +void TriFog( float flFogColor[3], float flStart, float flEnd, int bOn ); +void TriGetMatrix( const int pname, float *matrix ); +void TriFogParams( float flDensity, int iFogSkybox ); +void TriCullFace( TRICULLSTYLE mode ); + + +extern ref_api_t gEngfuncs; +extern ref_globals_t *gpGlobals; +extern cvar_t *gl_emboss_scale; +#if 0 +// +// renderer cvars +// +extern cvar_t *gl_texture_anisotropy; +extern cvar_t *gl_extensions; +extern cvar_t *gl_check_errors; +extern cvar_t *gl_texture_lodbias; +extern cvar_t *gl_texture_nearest; +extern cvar_t *gl_lightmap_nearest; +extern cvar_t *gl_keeptjunctions; + +extern cvar_t *gl_round_down; +extern cvar_t *gl_detailscale; +extern cvar_t *gl_wireframe; +extern cvar_t *gl_polyoffset; +extern cvar_t *gl_finish; +extern cvar_t *gl_nosort; +extern cvar_t *gl_clear; +extern cvar_t *gl_test; // cvar to testify new effects +extern cvar_t *gl_msaa; +extern cvar_t *gl_stencilbits; + +extern cvar_t *r_speeds; +extern cvar_t *r_fullbright; +extern cvar_t *r_norefresh; +extern cvar_t *r_showtree; // build graph of visible hull +extern cvar_t *r_lighting_extended; +extern cvar_t *r_lighting_modulate; +extern cvar_t *r_lighting_ambient; +extern cvar_t *r_studio_lambert; +extern cvar_t *r_detailtextures; +extern cvar_t *r_drawentities; +extern cvar_t *r_decals; +extern cvar_t *r_novis; +extern cvar_t *r_nocull; +extern cvar_t *r_lockpvs; +extern cvar_t *r_lockfrustum; +extern cvar_t *r_traceglow; +extern cvar_t *r_dynamic; +extern cvar_t *r_lightmap; +extern cvar_t *r_vbo; +extern cvar_t *r_vbo_dlightmode; + +extern cvar_t *vid_brightness; +extern cvar_t *vid_gamma; + +// +// engine shared convars +// +extern cvar_t *gl_showtextures; +extern cvar_t *tracerred; +extern cvar_t *tracergreen; +extern cvar_t *tracerblue; +extern cvar_t *traceralpha; +extern cvar_t *cl_lightstyle_lerping; +extern cvar_t *r_showhull; +#endif +// +// engine callbacks +// +#include "crtlib.h" + +#define Mem_Malloc( pool, size ) gEngfuncs._Mem_Alloc( pool, size, false, __FILE__, __LINE__ ) +#define Mem_Calloc( pool, size ) gEngfuncs._Mem_Alloc( pool, size, true, __FILE__, __LINE__ ) +#define Mem_Realloc( pool, ptr, size ) gEngfuncs._Mem_Realloc( pool, ptr, size, true, __FILE__, __LINE__ ) +#define Mem_Free( mem ) gEngfuncs._Mem_Free( mem, __FILE__, __LINE__ ) +#define Mem_AllocPool( name ) gEngfuncs._Mem_AllocPool( name, __FILE__, __LINE__ ) +#define Mem_FreePool( pool ) gEngfuncs._Mem_FreePool( pool, __FILE__, __LINE__ ) +#define Mem_EmptyPool( pool ) gEngfuncs._Mem_EmptyPool( pool, __FILE__, __LINE__ ) + +#endif // GL_LOCAL_H diff --git a/r_triapi.c b/r_triapi.c new file mode 100644 index 00000000..1ff6f817 --- /dev/null +++ b/r_triapi.c @@ -0,0 +1,355 @@ +/* +gl_triapi.c - TriAPI draw methods +Copyright (C) 2011 Uncle Mike +Copyright (C) 2019 a1batross + +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 3 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. +*/ + +#include "r_local.h" +#include "const.h" + +static struct +{ + int renderMode; // override kRenderMode from TriAPI + vec4_t triRGBA; +} ds; + +/* +=============================================================== + + TRIAPI IMPLEMENTATION + +=============================================================== +*/ +/* +============= +TriRenderMode + +set rendermode +============= +*/ +void TriRenderMode( int mode ) +{ + ds.renderMode = mode; +#if 0 + switch( mode ) + { + case kRenderNormal: + pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + pglDisable( GL_BLEND ); + pglDepthMask( GL_TRUE ); + break; + case kRenderTransAlpha: + pglEnable( GL_BLEND ); + pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + pglDepthMask( GL_FALSE ); + break; + case kRenderTransColor: + case kRenderTransTexture: + pglEnable( GL_BLEND ); + pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + break; + case kRenderGlow: + case kRenderTransAdd: + pglBlendFunc( GL_SRC_ALPHA, GL_ONE ); + pglEnable( GL_BLEND ); + pglDepthMask( GL_FALSE ); + break; + } +#endif +} + +/* +============= +TriBegin + +begin triangle sequence +============= +*/ +void TriBegin( int mode ) +{ +#if 0 + switch( mode ) + { + case TRI_POINTS: + mode = GL_POINTS; + break; + case TRI_TRIANGLES: + mode = GL_TRIANGLES; + break; + case TRI_TRIANGLE_FAN: + mode = GL_TRIANGLE_FAN; + break; + case TRI_QUADS: + mode = GL_QUADS; + break; + case TRI_LINES: + mode = GL_LINES; + break; + case TRI_TRIANGLE_STRIP: + mode = GL_TRIANGLE_STRIP; + break; + case TRI_QUAD_STRIP: + mode = GL_QUAD_STRIP; + break; + case TRI_POLYGON: + default: + mode = GL_POLYGON; + break; + } + + pglBegin( mode ); +#endif +} + +/* +============= +TriEnd + +draw triangle sequence +============= +*/ +void TriEnd( void ) +{ + //pglEnd( ); +} + +/* +============= +_TriColor4f + +============= +*/ +void _TriColor4f( float r, float g, float b, float a ) +{ + //pglColor4f( r, g, b, a ); +} + +/* +============= +TriColor4ub + +============= +*/ +void TriColor4ub( byte r, byte g, byte b, byte a ) +{ + ds.triRGBA[0] = r * (1.0f / 255.0f); + ds.triRGBA[1] = g * (1.0f / 255.0f); + ds.triRGBA[2] = b * (1.0f / 255.0f); + ds.triRGBA[3] = a * (1.0f / 255.0f); + + _TriColor4f( ds.triRGBA[0], ds.triRGBA[1], ds.triRGBA[2], 1.0f ); +} + +/* +================= +TriColor4f +================= +*/ +void TriColor4f( float r, float g, float b, float a ) +{ + if( ds.renderMode == kRenderTransAlpha ) + TriColor4ub( r * 255.9f, g * 255.9f, b * 255.9f, a * 255.0f ); + else _TriColor4f( r * a, g * a, b * a, 1.0 ); + + ds.triRGBA[0] = r; + ds.triRGBA[1] = g; + ds.triRGBA[2] = b; + ds.triRGBA[3] = a; +} + +/* +============= +TriTexCoord2f + +============= +*/ +void TriTexCoord2f( float u, float v ) +{ + //pglTexCoord2f( u, v ); +} + +/* +============= +TriVertex3fv + +============= +*/ +void TriVertex3fv( const float *v ) +{ + //pglVertex3fv( v ); +} + +/* +============= +TriVertex3f + +============= +*/ +void TriVertex3f( float x, float y, float z ) +{ + //pglVertex3f( x, y, z ); +} + +/* +============= +TriWorldToScreen + +convert world coordinates (x,y,z) into screen (x, y) +============= +*/ +int TriWorldToScreen( float *world, float *screen ) +{ + int retval; + +// retval = R_WorldToScreen( world, screen ); + + screen[0] = 0.5f * screen[0] * (float)RI.viewport[2]; + screen[1] = -0.5f * screen[1] * (float)RI.viewport[3]; + screen[0] += 0.5f * (float)RI.viewport[2]; + screen[1] += 0.5f * (float)RI.viewport[3]; + + return retval; +} + +/* +============= +TriSpriteTexture + +bind current texture +============= +*/ +int TriSpriteTexture( model_t *pSpriteModel, int frame ) +{ + int gl_texturenum; + + if(( gl_texturenum = R_GetSpriteTexture( pSpriteModel, frame )) == 0 ) + return 0; + + if( gl_texturenum <= 0 || gl_texturenum > MAX_TEXTURES ) + gl_texturenum = tr.defaultTexture; + + GL_Bind( XASH_TEXTURE0, gl_texturenum ); + + return 1; +} + +/* +============= +TriFog + +enables global fog on the level +============= +*/ +void TriFog( float flFogColor[3], float flStart, float flEnd, int bOn ) +{ +#if 0 + // overrided by internal fog + if( RI.fogEnabled ) return; + RI.fogCustom = bOn; + + // check for invalid parms + if( flEnd <= flStart ) + { + RI.fogCustom = false; + pglDisable( GL_FOG ); + return; + } + + if( RI.fogCustom ) + pglEnable( GL_FOG ); + else pglDisable( GL_FOG ); + + // copy fog params + RI.fogColor[0] = flFogColor[0] / 255.0f; + RI.fogColor[1] = flFogColor[1] / 255.0f; + RI.fogColor[2] = flFogColor[2] / 255.0f; + RI.fogStart = flStart; + RI.fogColor[3] = 1.0f; + RI.fogDensity = 0.0f; + RI.fogSkybox = true; + RI.fogEnd = flEnd; + + pglFogi( GL_FOG_MODE, GL_LINEAR ); + pglFogfv( GL_FOG_COLOR, RI.fogColor ); + pglFogf( GL_FOG_START, RI.fogStart ); + pglFogf( GL_FOG_END, RI.fogEnd ); + pglHint( GL_FOG_HINT, GL_NICEST ); +#endif +} + +/* +============= +TriGetMatrix + +very strange export +============= +*/ +void TriGetMatrix( const int pname, float *matrix ) +{ + //pglGetFloatv( pname, matrix ); +} + +/* +============= +TriForParams + +============= +*/ +void TriFogParams( float flDensity, int iFogSkybox ) +{ + RI.fogDensity = flDensity; + RI.fogSkybox = iFogSkybox; +} + +/* +============= +TriCullFace + +============= +*/ +void TriCullFace( TRICULLSTYLE mode ) +{ +#if 0 + int glMode; + + switch( mode ) + { + case TRI_FRONT: + glMode = GL_FRONT; + break; + default: + glMode = GL_NONE; + break; + } + + GL_Cull( mode ); +#endif +} + +/* +============= +TriBrightness +============= +*/ +void TriBrightness( float brightness ) +{ + float r, g, b; + + r = ds.triRGBA[0] * ds.triRGBA[3] * brightness; + g = ds.triRGBA[1] * ds.triRGBA[3] * brightness; + b = ds.triRGBA[2] * ds.triRGBA[3] * brightness; + + _TriColor4f( r, g, b, 1.0f ); +} + diff --git a/r_vgui.c b/r_vgui.c new file mode 100644 index 00000000..70d2740b --- /dev/null +++ b/r_vgui.c @@ -0,0 +1,225 @@ +/* +gl_vgui.c - OpenGL vgui draw methods +Copyright (C) 2011 Uncle Mike +Copyright (C) 2019 a1batross + +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 3 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. +*/ + +#include "r_local.h" + +#define VGUI_MAX_TEXTURES ( MAX_TEXTURES / 2 ) // a half of total textures count + +static int g_textures[VGUI_MAX_TEXTURES]; +static int g_textureId = 0; +static int g_iBoundTexture; + +/* +================ +VGUI_DrawInit + +Startup VGUI backend +================ +*/ +void GAME_EXPORT VGUI_DrawInit( void ) +{ + memset( g_textures, 0, sizeof( g_textures )); + g_textureId = g_iBoundTexture = 0; +} + +/* +================ +VGUI_DrawShutdown + +Release all textures +================ +*/ +void GAME_EXPORT VGUI_DrawShutdown( void ) +{ + int i; + + for( i = 1; i < g_textureId; i++ ) + { + GL_FreeTexture( g_textures[i] ); + } +} + +/* +================ +VGUI_GenerateTexture + +generate unique texture number +================ +*/ +int GAME_EXPORT VGUI_GenerateTexture( void ) +{ + if( ++g_textureId >= VGUI_MAX_TEXTURES ) + gEngfuncs.Host_Error( "VGUI_GenerateTexture: VGUI_MAX_TEXTURES limit exceeded\n" ); + return g_textureId; +} + +/* +================ +VGUI_UploadTexture + +Upload texture into video memory +================ +*/ +void GAME_EXPORT VGUI_UploadTexture( int id, const char *buffer, int width, int height ) +{ + rgbdata_t r_image; + char texName[32]; + + if( id <= 0 || id >= VGUI_MAX_TEXTURES ) + { + gEngfuncs.Con_DPrintf( S_ERROR "VGUI_UploadTexture: bad texture %i. Ignored\n", id ); + return; + } + + Q_snprintf( texName, sizeof( texName ), "*vgui%i", id ); + memset( &r_image, 0, sizeof( r_image )); + + r_image.width = width; + r_image.height = height; + r_image.type = PF_RGBA_32; + r_image.size = r_image.width * r_image.height * 4; + r_image.flags = IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA; + r_image.buffer = (byte *)buffer; + + g_textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE ); +} + +/* +================ +VGUI_CreateTexture + +Create empty rgba texture and upload them into video memory +================ +*/ +void GAME_EXPORT VGUI_CreateTexture( int id, int width, int height ) +{ + rgbdata_t r_image; + char texName[32]; + + if( id <= 0 || id >= VGUI_MAX_TEXTURES ) + { + gEngfuncs.Con_Reportf( S_ERROR "VGUI_CreateTexture: bad texture %i. Ignored\n", id ); + return; + } + + Q_snprintf( texName, sizeof( texName ), "*vgui%i", id ); + memset( &r_image, 0, sizeof( r_image )); + + r_image.width = width; + r_image.height = height; + r_image.type = PF_RGBA_32; + r_image.size = r_image.width * r_image.height * 4; + r_image.flags = IMAGE_HAS_ALPHA; + r_image.buffer = NULL; + + g_textures[id] = GL_LoadTextureInternal( texName, &r_image, TF_IMAGE|TF_NEAREST ); + g_iBoundTexture = id; +} + +void GAME_EXPORT VGUI_UploadTextureBlock( int id, int drawX, int drawY, const byte *rgba, int blockWidth, int blockHeight ) +{ + if( id <= 0 || id >= VGUI_MAX_TEXTURES || g_textures[id] == 0 || g_textures[id] == tr.whiteTexture ) + { + gEngfuncs.Con_Reportf( S_ERROR "VGUI_UploadTextureBlock: bad texture %i. Ignored\n", id ); + return; + } + + //pglTexSubImage2D( GL_TEXTURE_2D, 0, drawX, drawY, blockWidth, blockHeight, GL_RGBA, GL_UNSIGNED_BYTE, rgba ); + g_iBoundTexture = id; +} + +void GAME_EXPORT VGUI_SetupDrawingRect( int *pColor ) +{ + +} + +void GAME_EXPORT VGUI_SetupDrawingText( int *pColor ) +{ + +} + +void GAME_EXPORT VGUI_SetupDrawingImage( int *pColor ) +{ + +} + +void GAME_EXPORT VGUI_BindTexture( int id ) +{ + if( id > 0 && id < VGUI_MAX_TEXTURES && g_textures[id] ) + { + GL_Bind( XASH_TEXTURE0, g_textures[id] ); + g_iBoundTexture = id; + } + else + { + // NOTE: same as bogus index 2700 in GoldSrc + id = g_iBoundTexture = 1; + GL_Bind( XASH_TEXTURE0, g_textures[id] ); + } +} + +/* +================ +VGUI_GetTextureSizes + +returns wide and tall for currently binded texture +================ +*/ +void GAME_EXPORT VGUI_GetTextureSizes( int *width, int *height ) +{ + image_t *glt; + int texnum; + + if( g_iBoundTexture ) + texnum = g_textures[g_iBoundTexture]; + else texnum = tr.defaultTexture; + + glt = R_GetTexture( texnum ); + if( width ) *width = glt->srcWidth; + if( height ) *height = glt->srcHeight; +} + +/* +================ +VGUI_EnableTexture + +disable texturemode for fill rectangle +================ +*/ +void GAME_EXPORT VGUI_EnableTexture( qboolean enable ) +{ + +} + +/* +================ +VGUI_DrawQuad + +generic method to fill rectangle +================ +*/ +void GAME_EXPORT VGUI_DrawQuad( const vpoint_t *ul, const vpoint_t *lr ) +{ + int width, height; + float xscale, yscale; + + gEngfuncs.CL_GetScreenInfo( &width, &height ); + + xscale = gpGlobals->width / (float)width; + yscale = gpGlobals->height / (float)height; + + ASSERT( ul != NULL && lr != NULL ); +} diff --git a/wscript b/wscript new file mode 100644 index 00000000..8bed8fa4 --- /dev/null +++ b/wscript @@ -0,0 +1,55 @@ +#! /usr/bin/env python +# encoding: utf-8 +# mittorn, 2018 + +from waflib import Logs +import os +from fwgslib import get_subproject_name + +top = '.' + +def options(opt): + # stub + return + +def configure(conf): + # check for dedicated server build + if conf.options.DEDICATED: + return + + if conf.options.SUPPORT_BSP2_FORMAT: + conf.env.append_unique('DEFINES', 'SUPPORT_BSP2_FORMAT') + + conf.env.append_unique('DEFINES', 'REF_DLL') + +def build(bld): + if bld.env.DEDICATED: + return + + bld.load_envs() + name = get_subproject_name(bld) + bld.env = bld.all_envs[name] + + libs = [ 'M' ] + + source = bld.path.ant_glob(['*.c']) + + source += [ '../engine/common/mathlib.c', '../engine/common/crtlib.c', '../engine/common/matrixlib.c' ] + + includes = ['.', + '../engine', + '../engine/common', + '../engine/server', + '../engine/client', + '../common', + '../pm_shared' ] + + bld.shlib( + source = source, + target = name, + features = 'c', + includes = includes, + use = libs, + install_path = bld.env.LIBDIR, + subsystem = bld.env.MSVC_SUBSYSTEM + ) From ae6b460f35271bbc08712dcb875c76426ed962b5 Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 20 Mar 2019 15:26:53 +0700 Subject: [PATCH 002/115] ref_soft: Implement internal color tables --- r_context.c | 12 +++++++----- r_glblit.c | 33 +++++++++++++++++++++++++++++++-- r_image.c | 20 +++++++++++++++----- r_local.h | 7 +++++++ 4 files changed, 60 insertions(+), 12 deletions(-) diff --git a/r_context.c b/r_context.c index 55e8ff12..f7072be2 100644 --- a/r_context.c +++ b/r_context.c @@ -623,6 +623,13 @@ qboolean R_Init() { gl_emboss_scale = gEngfuncs.Cvar_Get( "gl_emboss_scale", "0", FCVAR_ARCHIVE|FCVAR_LATCH, "fake bumpmapping scale" ); // create the window and set up the context + r_temppool = Mem_AllocPool( "ref_sw zone" ); + + vid.width = 1920; + vid.height = 1080; + vid.rowbytes = 1920; // rowpixels + + vid.buffer = Mem_Malloc( r_temppool, 1920*1080*sizeof( pixel_t ) ); if( !gEngfuncs.R_Init_Video( REF_GL )) // request GL context { gEngfuncs.R_Free_Video(); @@ -630,12 +637,7 @@ qboolean R_Init() gEngfuncs.Host_Error( "Can't initialize video subsystem\nProbably driver was not installed" ); return false; } - r_temppool = Mem_AllocPool( "ref_sw zone" ); - vid.width = 1920; - vid.height = 1080; - vid.rowbytes = 1920; // rowpixels - vid.buffer = Mem_Malloc( r_temppool, 1920*1080*sizeof( pixel_t ) ); R_InitImages(); return true; diff --git a/r_glblit.c b/r_glblit.c index 9e8214d1..776feb02 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -35,10 +35,12 @@ static void APIENTRY GL_DebugOutput( GLuint source, GLuint type, GLuint id, GLui } } int tex; +unsigned short *buffer; #define LOAD(x) p##x = gEngfuncs.GL_GetProcAddress(#x) void R_InitBlit() { + int i; LOAD(glBegin); LOAD(glEnd); LOAD(glTexCoord2f); @@ -69,12 +71,39 @@ void R_InitBlit() // enable all the low priority messages pglDebugMessageControlARB( GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, true ); pglGenTextures( 1, &tex ); -} + buffer = Mem_Malloc( r_temppool, 1920*1080*2 ); + + for( i = 0; i < 256; i++ ) + { + unsigned int r,g,b; + // 332 to 565 + r = ((i >> (8 - 3) )<< 2 ) & MASK(5); + g = ((i >> (8 - 3 - 3)) << 3) & MASK(6); + b = ((i >> (8 - 3 - 3 - 2)) << 3) & MASK(5); + vid.screen_major[i] = r << (6 + 5) | (g << 5) | b; + + // restore minor GBRGBRGB + r = MOVE_BIT(i, 5, 1) | MOVE_BIT(i, 2, 0); + g = MOVE_BIT(i, 7, 2) | MOVE_BIT(i, 4, 1) | MOVE_BIT(i, 1, 0); + b = MOVE_BIT(i, 6, 2) | MOVE_BIT(i, 3, 1) | MOVE_BIT(i, 0, 0); + vid.screen_minor[i] = r << (6 + 5) | (g << 5) | b; + } +} void R_BlitScreen() { //memset( vid.buffer, 10, vid.width * vid.height ); + int i; + byte *buf = vid.buffer; + + for( i = 0; i < vid.width * vid.height;i++) + { + byte major = buf[(i<<1)+1]; + byte minor = buf[(i<<1)]; + + buffer[i] = vid.screen_major[major]|vid.screen_minor[minor]; + } pglBindTexture(GL_TEXTURE_2D, tex); pglViewport( 0, 0, gpGlobals->width, gpGlobals->height ); pglMatrixMode( GL_PROJECTION ); @@ -90,7 +119,7 @@ void R_BlitScreen() pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); //gEngfuncs.Con_Printf("%d\n",pglGetError()); - pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vid.width, vid.height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, vid.buffer ); + pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vid.width, vid.height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, buffer ); //gEngfuncs.Con_Printf("%d\n",pglGetError()); pglBegin( GL_QUADS ); pglTexCoord2f( 0, 0 ); diff --git a/r_image.c b/r_image.c index 166060bc..778ce912 100644 --- a/r_image.c +++ b/r_image.c @@ -503,24 +503,34 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) gEngfuncs.Con_Printf("%s %d %d\n", tex->name, tex->width, tex->height ); + Assert( pic != NULL ); + Assert( tex != NULL ); + if( !pic->buffer ) return true; tex->pixels[0] = Mem_Calloc( r_temppool, tex->width * tex->height * sizeof(pixel_t) + 64 ); + for( i = 0; i < tex->width * tex->height; i++ ) { - unsigned int r, g, b; + unsigned int r, g, b, major, minor; + r = pic->buffer[i * 4 + 0] * BIT(5) / 256; g = pic->buffer[i * 4 + 1] * BIT(6) / 256; b = pic->buffer[i * 4 + 2] * BIT(5) / 256; - /// TODO: use internal rgb565-based palette for textures and screen - tex->pixels[0][i] = r << (6 + 5) | (g << 5) | b; + // 565 to 332 + major = (((r >> 2) & MASK(3)) << 5) |( (( (g >> 3) & MASK(3)) << 2 ) )| (((b >> 3) & MASK(2))); + + // save minor GBRGBRGB + minor = MOVE_BIT(r,1,5) | MOVE_BIT(r,0,2) | MOVE_BIT(g,2,7) | MOVE_BIT(g,1,4) | MOVE_BIT(g,0,1) | MOVE_BIT(b,2,6)| MOVE_BIT(b,1,3)|MOVE_BIT(b,0,0); + + tex->pixels[0][i] = major << 8 | (minor & 0xFF); } + /// TODO: generate mipmaps #if 0 - Assert( pic != NULL ); - Assert( tex != NULL ); + GL_SetTextureTarget( tex, pic ); // must be first diff --git a/r_local.h b/r_local.h index 62b7a668..7058201f 100644 --- a/r_local.h +++ b/r_local.h @@ -88,6 +88,11 @@ extern byte *r_temppool; #define CULL_VISFRAME 3 // culled by PVS #define CULL_OTHER 4 // culled by other reason +// bit operation helpers +#define MASK(x) (BIT(x+1)-1) +#define GET_BIT(s,b) ((s & (1 << b)) >> b) +#define MOVE_BIT(s, f, t) (GET_BIT(s,f) << t ) + /* skins will be outline flood filled and mip mapped @@ -124,6 +129,8 @@ typedef struct pixel_t *buffer; // invisible buffer pixel_t *colormap; // 256 * VID_GRADES size pixel_t *alphamap; // 256 * 256 translucency map + pixel_t screen_minor[256]; + pixel_t screen_major[256]; int rowbytes; // may be > width if displayed in a window // can be negative for stupid dibs int width; From f23ecc6895951fd15aa4c7d0ee8e4cd5293f7bb9 Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 20 Mar 2019 21:44:21 +0700 Subject: [PATCH 003/115] ref_soft: Implement rendermodes, colors, alpha textures/blending --- r_context.c | 1 + r_draw.c | 40 ++++++++++++++-- r_glblit.c | 128 ++++++++++++++++++++++++++++++++++++++++++++-------- r_image.c | 23 ++++++++-- r_local.h | 16 ++++++- r_triapi.c | 26 +++++++++-- 6 files changed, 204 insertions(+), 30 deletions(-) diff --git a/r_context.c b/r_context.c index f7072be2..7c22764e 100644 --- a/r_context.c +++ b/r_context.c @@ -376,6 +376,7 @@ void R_AllowFog(qboolean allowed) void GL_SetRenderMode(int mode) { + vid.rendermode = mode; /// TODO: table shading/blending??? /// maybe, setup block drawing function pointers here } diff --git a/r_draw.c b/r_draw.c index aa9c8ba7..9aeb1933 100644 --- a/r_draw.c +++ b/r_draw.c @@ -108,12 +108,12 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, { sv = (skip + v)*(t2-t1)/h + t1; source = pic->pixels[0] + sv*pic->width + s1; - if (w == s2 - s1) - memcpy (dest, source, w * 2); - else { f = 0; fstep = s2*0x10000/w; + if( w == s2 - s1 ) + fstep = 0x10000; +#if 0 for (u=0 ; u>16]; @@ -125,6 +125,37 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, dest[u+3] = source[f>>16]; f += fstep; } +#else + for (u=0 ; u>16]; + int alpha = vid.alpha; + + if( pic->transparent ) + { + alpha &= src >> 16 - 3; + src = src << 3; + } + + if( vid.color != COLOR_WHITE ) + src = vid.modmap[src & 0xff00|(vid.color>>8)] << 8 | (src & vid.color & 0xff) | ((src & 0xff) >> 1); + + if( vid.rendermode == kRenderTransAdd) + { + pixel_t screen = dest[u]; + dest[u] = vid.addmap[src & 0xff00|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 0); + } + else if( alpha < 7) // && (vid.rendermode == kRenderTransAlpha || vid.rendermode == kRenderTransTexture ) ) + { + pixel_t screen = dest[u]; + dest[u] = vid.alphamap[(vid.alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 1); + + } + else + dest[u] = src; + f += fstep; + } +#endif } } } @@ -160,7 +191,7 @@ void R_DrawTileClear( int texnum, int x, int y, int w, int h ) image_t *pic; pixel_t *psrc, *pdest; - //GL_SetRenderMode( kRenderNormal ); + GL_SetRenderMode( kRenderNormal ); _TriColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); GL_Bind( XASH_TEXTURE0, texnum ); @@ -239,6 +270,7 @@ R_Set2DMode */ void R_Set2DMode( qboolean enable ) { + vid.color = COLOR_WHITE; if( enable ) { // if( glState.in2DMode ) diff --git a/r_glblit.c b/r_glblit.c index 776feb02..f92cd824 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -38,9 +38,103 @@ int tex; unsigned short *buffer; #define LOAD(x) p##x = gEngfuncs.GL_GetProcAddress(#x) -void R_InitBlit() + +void R_BuildScreenMap() { int i; +#ifdef SEPARATE_BLIT + for( i = 0; i < 256; i++ ) + { + unsigned int r,g,b; + + // 332 to 565 + r = ((i >> (8 - 3) )<< 2 ) & MASK(5); + g = ((i >> (8 - 3 - 3)) << 3) & MASK(6); + b = ((i >> (8 - 3 - 3 - 2)) << 3) & MASK(5); + vid.screen_major[i] = r << (6 + 5) | (g << 5) | b; + + + // restore minor GBRGBRGB + r = MOVE_BIT(i, 5, 1) | MOVE_BIT(i, 2, 0); + g = MOVE_BIT(i, 7, 2) | MOVE_BIT(i, 4, 1) | MOVE_BIT(i, 1, 0); + b = MOVE_BIT(i, 6, 2) | MOVE_BIT(i, 3, 1) | MOVE_BIT(i, 0, 0); + vid.screen_minor[i] = r << (6 + 5) | (g << 5) | b; + + } +#else + for( i = 0; i < 256; i++ ) + { + unsigned int r,g,b , major, j; + + // 332 to 565 + r = ((i >> (8 - 3) )<< 2 ) & MASK(5); + g = ((i >> (8 - 3 - 3)) << 3) & MASK(6); + b = ((i >> (8 - 3 - 3 - 2)) << 3) & MASK(5); + major = r << (6 + 5) | (g << 5) | b; + + + for( j = 0; j < 256; j++ ) + { + // restore minor GBRGBRGB + r = MOVE_BIT(i, 5, 1) | MOVE_BIT(i, 2, 0); + g = MOVE_BIT(i, 7, 2) | MOVE_BIT(i, 4, 1) | MOVE_BIT(i, 1, 0); + b = MOVE_BIT(i, 6, 2) | MOVE_BIT(i, 3, 1) | MOVE_BIT(i, 0, 0); + vid.screen[(i<<8)|j] = r << (6 + 5) | (g << 5) | b | major; + + } + + } +#endif +} + +void R_BuildBlendMaps() +{ + unsigned int r1, g1, b1; + unsigned int r2, g2, b2; + + for( r1 = 0; r1 < BIT(3); r1++ ) + for( g1 = 0; g1 < BIT(3); g1++ ) + for( b1 = 0; b1 < BIT(2); b1++ ) + for( r2 = 0; r2 < BIT(3); r2++ ) + for( g2 = 0; g2 < BIT(3); g2++ ) + for( b2 = 0; b2 < BIT(2); b2++ ) + { + unsigned int r, g, b; + unsigned short index1 = r1 << (2 + 3) | g1 << 2 | b1; + unsigned short index2 = (r2 << (2 + 3) | g2 << 2 | b2) << 8; + unsigned int a; + + r = r1 + r2; + g = g1 + g2; + b = b1 + b2; + if( r > MASK(2) ) + r = MASK(2); + if( g > MASK(2) ) + g = MASK(2); + if( b > MASK(1) ) + b = MASK(1); + ASSERT(!vid.addmap[index2|index1]); + + vid.addmap[index2|index1] = r << (2 + 3) | g << 2 | b; + r = r1 * r2 / MASK(2); + g = g1 * g2 / MASK(2); + b = b1 * b2 / MASK(1); + vid.modmap[index2|index1] = r << (2 + 3) | g << 2 | b; + + for( a = 0; a < 8; a++ ) + { + r = r1 * a / 7 + r2 * (7 - a) / 7; + g = g1 * a / 7 + g2 * (7 - a) / 7; + b = b1 * a / 7 + b2 * (7 - a) / 7; + vid.alphamap[a << 16|index2|index1] = r << (2 + 3) | g << 2 | b; + } + + } +} + +void R_InitBlit() +{ + LOAD(glBegin); LOAD(glEnd); LOAD(glTexCoord2f); @@ -58,7 +152,7 @@ void R_InitBlit() LOAD(glGetError); LOAD(glGenTextures); LOAD(glTexParameteri); - +#ifdef GLDEBUG if( gpGlobals->developer ) { gEngfuncs.Con_Reportf( "Installing GL_DebugOutput...\n"); @@ -70,25 +164,14 @@ void R_InitBlit() // enable all the low priority messages pglDebugMessageControlARB( GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, true ); +#endif pglGenTextures( 1, &tex ); - buffer = Mem_Malloc( r_temppool, 1920*1080*2 ); - for( i = 0; i < 256; i++ ) - { - unsigned int r,g,b; - // 332 to 565 - r = ((i >> (8 - 3) )<< 2 ) & MASK(5); - g = ((i >> (8 - 3 - 3)) << 3) & MASK(6); - b = ((i >> (8 - 3 - 3 - 2)) << 3) & MASK(5); - vid.screen_major[i] = r << (6 + 5) | (g << 5) | b; + buffer = Mem_Malloc( r_temppool, 1920*1080*2 ); - // restore minor GBRGBRGB - r = MOVE_BIT(i, 5, 1) | MOVE_BIT(i, 2, 0); - g = MOVE_BIT(i, 7, 2) | MOVE_BIT(i, 4, 1) | MOVE_BIT(i, 1, 0); - b = MOVE_BIT(i, 6, 2) | MOVE_BIT(i, 3, 1) | MOVE_BIT(i, 0, 0); - vid.screen_minor[i] = r << (6 + 5) | (g << 5) | b; - } + R_BuildScreenMap(); + R_BuildBlendMaps(); } void R_BlitScreen() @@ -99,11 +182,18 @@ void R_BlitScreen() for( i = 0; i < vid.width * vid.height;i++) { +#ifdef SEPARATE_BLIT + // need only 1024 bytes table, but slower + // wtf?? maybe some prefetch??? byte major = buf[(i<<1)+1]; byte minor = buf[(i<<1)]; - buffer[i] = vid.screen_major[major]|vid.screen_minor[minor]; + buffer[i] = vid.screen_major[major] |vid.screen_minor[minor]; +#else + buffer[i] = vid.screen[vid.buffer[i]]; +#endif } + pglBindTexture(GL_TEXTURE_2D, tex); pglViewport( 0, 0, gpGlobals->width, gpGlobals->height ); pglMatrixMode( GL_PROJECTION ); @@ -119,6 +209,7 @@ void R_BlitScreen() pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); //gEngfuncs.Con_Printf("%d\n",pglGetError()); + pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vid.width, vid.height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, buffer ); //gEngfuncs.Con_Printf("%d\n",pglGetError()); pglBegin( GL_QUADS ); @@ -136,4 +227,5 @@ void R_BlitScreen() pglEnd(); pglDisable( GL_TEXTURE_2D ); gEngfuncs.GL_SwapBuffers(); + memset( vid.buffer, 0, vid.width * vid.height * 2 ); } diff --git a/r_image.c b/r_image.c index 778ce912..07900cbf 100644 --- a/r_image.c +++ b/r_image.c @@ -220,7 +220,7 @@ static void GL_SetTextureFormat( image_t *tex, pixformat_t format, int channelMa qboolean haveAlpha = ( channelMask & IMAGE_HAS_ALPHA ); Assert( tex != NULL ); - tex->transparent = !!( channelMask & IMAGE_HAS_ALPHA ); + //tex->transparent = !!( channelMask & IMAGE_HAS_ALPHA ); } /* @@ -509,16 +509,26 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) if( !pic->buffer ) return true; + /// TODO: generate mipmaps + + if( tex->flags & TF_HAS_ALPHA ) + tex->transparent = true; + tex->pixels[0] = Mem_Calloc( r_temppool, tex->width * tex->height * sizeof(pixel_t) + 64 ); for( i = 0; i < tex->width * tex->height; i++ ) { unsigned int r, g, b, major, minor; - +#if 0 + r = pic->buffer[i * 4 + 0] * MASK(5-1) / 255; + g = pic->buffer[i * 4 + 1] * MASK(6-1) / 255; + b = pic->buffer[i * 4 + 2] * MASK(5-1) / 255; +#else + // seems to look better r = pic->buffer[i * 4 + 0] * BIT(5) / 256; g = pic->buffer[i * 4 + 1] * BIT(6) / 256; b = pic->buffer[i * 4 + 2] * BIT(5) / 256; - +#endif // 565 to 332 major = (((r >> 2) & MASK(3)) << 5) |( (( (g >> 3) & MASK(3)) << 2 ) )| (((b >> 3) & MASK(2))); @@ -526,9 +536,14 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) minor = MOVE_BIT(r,1,5) | MOVE_BIT(r,0,2) | MOVE_BIT(g,2,7) | MOVE_BIT(g,1,4) | MOVE_BIT(g,0,1) | MOVE_BIT(b,2,6)| MOVE_BIT(b,1,3)|MOVE_BIT(b,0,0); tex->pixels[0][i] = major << 8 | (minor & 0xFF); + if( tex->transparent ) + { + unsigned int alpha = (pic->buffer[i * 4 + 3] * 8 / 256) << (16 - 3); + tex->pixels[0][i] = (tex->pixels[0][i] >> 3) | alpha; + } } - /// TODO: generate mipmaps + #if 0 diff --git a/r_local.h b/r_local.h index 7058201f..1548f63e 100644 --- a/r_local.h +++ b/r_local.h @@ -124,13 +124,27 @@ typedef struct vrect_s struct vrect_s *pnext; } vrect_t; +#define COLOR_WHITE 0xFFFF +#define SEPARATE_BLIT typedef struct { pixel_t *buffer; // invisible buffer pixel_t *colormap; // 256 * VID_GRADES size - pixel_t *alphamap; // 256 * 256 translucency map + //pixel_t *alphamap; // 256 * 256 translucency map +#ifdef SEPARATE_BLIT pixel_t screen_minor[256]; pixel_t screen_major[256]; +#else + pixel_t screen[256*256]; +#endif + byte addmap[256*256]; + byte modmap[256*256]; + pixel_t alphamap[8*256*256]; + pixel_t color; + byte alpha; + + // maybe compute colormask for minor byte? + int rendermode; int rowbytes; // may be > width if displayed in a window // can be negative for stupid dibs int width; diff --git a/r_triapi.c b/r_triapi.c index 1ff6f817..1ee810b4 100644 --- a/r_triapi.c +++ b/r_triapi.c @@ -39,7 +39,7 @@ set rendermode */ void TriRenderMode( int mode ) { - ds.renderMode = mode; + ds.renderMode = vid.rendermode = mode; #if 0 switch( mode ) { @@ -130,9 +130,29 @@ _TriColor4f ============= */ -void _TriColor4f( float r, float g, float b, float a ) +void _TriColor4f( float rr, float gg, float bb, float aa ) { //pglColor4f( r, g, b, a ); + unsigned short r,g,b; + + if( rr == 1 && gg == 1 && bb == 1 ) + { + vid.color = COLOR_WHITE; + return; + } + + r = rr * 31, g = gg * 63, b = bb * 31; + + vid.alpha = aa * 7; + if( vid.alpha > 7 ) + vid.alpha = 7; + + unsigned int major = (((r >> 2) & MASK(3)) << 5) |( (( (g >> 3) & MASK(3)) << 2 ) )| (((b >> 3) & MASK(2))); + + // save minor GBRGBRGB + unsigned int minor = MOVE_BIT(r,1,5) | MOVE_BIT(r,0,2) | MOVE_BIT(g,2,7) | MOVE_BIT(g,1,4) | MOVE_BIT(g,0,1) | MOVE_BIT(b,2,6)| MOVE_BIT(b,1,3)|MOVE_BIT(b,0,0); + + vid.color = major << 8 | (minor & 0xFF); } /* @@ -148,7 +168,7 @@ void TriColor4ub( byte r, byte g, byte b, byte a ) ds.triRGBA[2] = b * (1.0f / 255.0f); ds.triRGBA[3] = a * (1.0f / 255.0f); - _TriColor4f( ds.triRGBA[0], ds.triRGBA[1], ds.triRGBA[2], 1.0f ); + _TriColor4f( ds.triRGBA[0], ds.triRGBA[1], ds.triRGBA[2], ds.triRGBA[3] ); //1.0f ); } /* From 6784b9062e5d2511e543973a5192d223d26bce1d Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 20 Mar 2019 21:55:04 +0700 Subject: [PATCH 004/115] ref_soft: hide color loops to macro --- r_glblit.c | 73 ++++++++++++++++++++++++++---------------------------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/r_glblit.c b/r_glblit.c index f92cd824..f80a7ef8 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -87,49 +87,46 @@ void R_BuildScreenMap() #endif } +#define FOR_EACH_COLOR(x) for( r##x = 0; r##x < BIT(3); r##x++ ) for( g##x = 0; g##x < BIT(3); g##x++ ) for( b##x = 0; b##x < BIT(2); b##x++ ) + void R_BuildBlendMaps() { unsigned int r1, g1, b1; unsigned int r2, g2, b2; - for( r1 = 0; r1 < BIT(3); r1++ ) - for( g1 = 0; g1 < BIT(3); g1++ ) - for( b1 = 0; b1 < BIT(2); b1++ ) - for( r2 = 0; r2 < BIT(3); r2++ ) - for( g2 = 0; g2 < BIT(3); g2++ ) - for( b2 = 0; b2 < BIT(2); b2++ ) - { - unsigned int r, g, b; - unsigned short index1 = r1 << (2 + 3) | g1 << 2 | b1; - unsigned short index2 = (r2 << (2 + 3) | g2 << 2 | b2) << 8; - unsigned int a; - - r = r1 + r2; - g = g1 + g2; - b = b1 + b2; - if( r > MASK(2) ) - r = MASK(2); - if( g > MASK(2) ) - g = MASK(2); - if( b > MASK(1) ) - b = MASK(1); - ASSERT(!vid.addmap[index2|index1]); - - vid.addmap[index2|index1] = r << (2 + 3) | g << 2 | b; - r = r1 * r2 / MASK(2); - g = g1 * g2 / MASK(2); - b = b1 * b2 / MASK(1); - vid.modmap[index2|index1] = r << (2 + 3) | g << 2 | b; - - for( a = 0; a < 8; a++ ) - { - r = r1 * a / 7 + r2 * (7 - a) / 7; - g = g1 * a / 7 + g2 * (7 - a) / 7; - b = b1 * a / 7 + b2 * (7 - a) / 7; - vid.alphamap[a << 16|index2|index1] = r << (2 + 3) | g << 2 | b; - } - - } + FOR_EACH_COLOR(1)FOR_EACH_COLOR(2) + { + unsigned int r, g, b; + unsigned short index1 = r1 << (2 + 3) | g1 << 2 | b1; + unsigned short index2 = (r2 << (2 + 3) | g2 << 2 | b2) << 8; + unsigned int a; + + r = r1 + r2; + g = g1 + g2; + b = b1 + b2; + if( r > MASK(2) ) + r = MASK(2); + if( g > MASK(2) ) + g = MASK(2); + if( b > MASK(1) ) + b = MASK(1); + ASSERT(!vid.addmap[index2|index1]); + + vid.addmap[index2|index1] = r << (2 + 3) | g << 2 | b; + r = r1 * r2 / MASK(2); + g = g1 * g2 / MASK(2); + b = b1 * b2 / MASK(1); + vid.modmap[index2|index1] = r << (2 + 3) | g << 2 | b; + + for( a = 0; a < 8; a++ ) + { + r = r1 * a / 7 + r2 * (7 - a) / 7; + g = g1 * a / 7 + g2 * (7 - a) / 7; + b = b1 * a / 7 + b2 * (7 - a) / 7; + vid.alphamap[a << 16|index2|index1] = r << (2 + 3) | g << 2 | b; + } + + } } void R_InitBlit() From ce27aad67b02c4d0d57237edc071e257f0fa84ad Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 21 Mar 2019 17:56:42 +0700 Subject: [PATCH 005/115] ref_soft: Fix alpha blending, optimize blitting --- r_draw.c | 10 +++++++--- r_glblit.c | 22 ++++++++-------------- r_local.h | 4 ++-- r_triapi.c | 9 ++++++--- 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/r_draw.c b/r_draw.c index 9aeb1933..53dd1776 100644 --- a/r_draw.c +++ b/r_draw.c @@ -130,6 +130,7 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, { pixel_t src = source[f>>16]; int alpha = vid.alpha; + f += fstep; if( pic->transparent ) { @@ -137,8 +138,11 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, src = src << 3; } + if( alpha == 0 ) + continue; + if( vid.color != COLOR_WHITE ) - src = vid.modmap[src & 0xff00|(vid.color>>8)] << 8 | (src & vid.color & 0xff) | ((src & 0xff) >> 1); + src = vid.modmap[src & 0xff00|(vid.color>>8)] << 8 | (src & vid.color & 0xff) | ((src & 0xff) >> 3); if( vid.rendermode == kRenderTransAdd) { @@ -148,12 +152,12 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, else if( alpha < 7) // && (vid.rendermode == kRenderTransAlpha || vid.rendermode == kRenderTransTexture ) ) { pixel_t screen = dest[u]; - dest[u] = vid.alphamap[(vid.alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 1); + dest[u] = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) >> 3 | ((src & 0xff) >> 3); } else dest[u] = src; - f += fstep; + } #endif } diff --git a/r_glblit.c b/r_glblit.c index f80a7ef8..434be575 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -34,7 +34,6 @@ static void APIENTRY GL_DebugOutput( GLuint source, GLuint type, GLuint id, GLui break; } } -int tex; unsigned short *buffer; #define LOAD(x) p##x = gEngfuncs.GL_GetProcAddress(#x) @@ -76,9 +75,9 @@ void R_BuildScreenMap() for( j = 0; j < 256; j++ ) { // restore minor GBRGBRGB - r = MOVE_BIT(i, 5, 1) | MOVE_BIT(i, 2, 0); - g = MOVE_BIT(i, 7, 2) | MOVE_BIT(i, 4, 1) | MOVE_BIT(i, 1, 0); - b = MOVE_BIT(i, 6, 2) | MOVE_BIT(i, 3, 1) | MOVE_BIT(i, 0, 0); + r = MOVE_BIT(j, 5, 1) | MOVE_BIT(j, 2, 0); + g = MOVE_BIT(j, 7, 2) | MOVE_BIT(j, 4, 1) | MOVE_BIT(j, 1, 0); + b = MOVE_BIT(j, 6, 2) | MOVE_BIT(j, 3, 1) | MOVE_BIT(j, 0, 0); vid.screen[(i<<8)|j] = r << (6 + 5) | (g << 5) | b | major; } @@ -116,13 +115,15 @@ void R_BuildBlendMaps() r = r1 * r2 / MASK(2); g = g1 * g2 / MASK(2); b = b1 * b2 / MASK(1); + vid.modmap[index2|index1] = r << (2 + 3) | g << 2 | b; for( a = 0; a < 8; a++ ) { - r = r1 * a / 7 + r2 * (7 - a) / 7; - g = g1 * a / 7 + g2 * (7 - a) / 7; - b = b1 * a / 7 + b2 * (7 - a) / 7; + r = r1 * (7 - a) / 7 + r2 * a / 7; + g = g1 * (7 - a) / 7 + g2 * a / 7; + b = b1 * (7 - a) / 7 + b2 * a / 7; + //if( b == 1 ) b = 0; vid.alphamap[a << 16|index2|index1] = r << (2 + 3) | g << 2 | b; } @@ -162,8 +163,6 @@ void R_InitBlit() // enable all the low priority messages pglDebugMessageControlARB( GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, true ); #endif - pglGenTextures( 1, &tex ); - buffer = Mem_Malloc( r_temppool, 1920*1080*2 ); @@ -191,7 +190,6 @@ void R_BlitScreen() #endif } - pglBindTexture(GL_TEXTURE_2D, tex); pglViewport( 0, 0, gpGlobals->width, gpGlobals->height ); pglMatrixMode( GL_PROJECTION ); pglLoadIdentity(); @@ -200,12 +198,8 @@ void R_BlitScreen() pglLoadIdentity(); pglEnable( GL_TEXTURE_2D ); - pglBindTexture(GL_TEXTURE_2D, tex); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - //gEngfuncs.Con_Printf("%d\n",pglGetError()); pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vid.width, vid.height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, buffer ); //gEngfuncs.Con_Printf("%d\n",pglGetError()); diff --git a/r_local.h b/r_local.h index 1548f63e..1cc2262e 100644 --- a/r_local.h +++ b/r_local.h @@ -125,7 +125,7 @@ typedef struct vrect_s } vrect_t; #define COLOR_WHITE 0xFFFF -#define SEPARATE_BLIT +//#define SEPARATE_BLIT typedef struct { pixel_t *buffer; // invisible buffer @@ -139,7 +139,7 @@ typedef struct #endif byte addmap[256*256]; byte modmap[256*256]; - pixel_t alphamap[8*256*256]; + byte alphamap[8*256*256]; pixel_t color; byte alpha; diff --git a/r_triapi.c b/r_triapi.c index 1ee810b4..7f405fb0 100644 --- a/r_triapi.c +++ b/r_triapi.c @@ -135,6 +135,12 @@ void _TriColor4f( float rr, float gg, float bb, float aa ) //pglColor4f( r, g, b, a ); unsigned short r,g,b; + + vid.alpha = aa * 7; + if( vid.alpha > 7 ) + vid.alpha = 7; + //gEngfuncs.Con_Printf("%d\n", vid.alpha); + if( rr == 1 && gg == 1 && bb == 1 ) { vid.color = COLOR_WHITE; @@ -143,9 +149,6 @@ void _TriColor4f( float rr, float gg, float bb, float aa ) r = rr * 31, g = gg * 63, b = bb * 31; - vid.alpha = aa * 7; - if( vid.alpha > 7 ) - vid.alpha = 7; unsigned int major = (((r >> 2) & MASK(3)) << 5) |( (( (g >> 3) & MASK(3)) << 2 ) )| (((b >> 3) & MASK(2))); From 2b521ee2014b74067dacae5db1a5746d5a04b2a5 Mon Sep 17 00:00:00 2001 From: mittorn Date: Fri, 22 Mar 2019 19:33:14 +0700 Subject: [PATCH 006/115] ref_soft: Copy world renderer from zq/q2, does not render anything now --- r_bsp.c | 626 ++++++++++++++++++++ r_context.c | 105 +--- r_draw.c | 8 +- r_edge.c | 1132 ++++++++++++++++++++++++++++++++++++ r_glblit.c | 2 +- r_light.c | 499 ++++++++++++++++ r_local.h | 516 ++++++++++++++++- r_main.c | 1576 +++++++++++++++++++++++++++++++++++++++++++++++++++ r_misc.c | 421 ++++++++++++++ r_rast.c | 852 ++++++++++++++++++++++++++++ r_scan.c | 593 +++++++++++++++++++ r_surf.c | 753 ++++++++++++++++++++++++ 12 files changed, 6975 insertions(+), 108 deletions(-) create mode 100644 r_bsp.c create mode 100644 r_edge.c create mode 100644 r_light.c create mode 100644 r_main.c create mode 100644 r_misc.c create mode 100644 r_rast.c create mode 100644 r_scan.c create mode 100644 r_surf.c diff --git a/r_bsp.c b/r_bsp.c new file mode 100644 index 00000000..4f1c49ef --- /dev/null +++ b/r_bsp.c @@ -0,0 +1,626 @@ +/* +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. + +*/ +// r_bsp.c + +#include "r_local.h" + +// +// current entity info +// +qboolean insubmodel; +vec3_t modelorg; // modelorg is the viewpoint reletive to + // the currently rendering entity +vec3_t r_entorigin; // the currently rendering entity in world + // coordinates + +float entity_rotation[3][3]; + +int r_currentbkey; + +typedef enum {touchessolid, drawnode, nodrawnode} solidstate_t; + +#define MAX_BMODEL_VERTS 500 // 6K +#define MAX_BMODEL_EDGES 1000 // 12K + +static mvertex_t *pbverts; +static bedge_t *pbedges; +static int numbverts, numbedges; + +static mvertex_t *pfrontenter, *pfrontexit; + +static qboolean makeclippededge; + + +//=========================================================================== + +/* +================ +R_EntityRotate +================ +*/ +void R_EntityRotate (vec3_t vec) +{ + vec3_t tvec; + + VectorCopy (vec, tvec); + vec[0] = DotProduct (entity_rotation[0], tvec); + vec[1] = DotProduct (entity_rotation[1], tvec); + vec[2] = DotProduct (entity_rotation[2], tvec); +} + + +/* +================ +R_RotateBmodel +================ +*/ +void R_RotateBmodel (void) +{ + float angle, s, c, temp1[3][3], temp2[3][3], temp3[3][3]; + +// TODO: should use a look-up table +// TODO: should really be stored with the entity instead of being reconstructed +// TODO: could cache lazily, stored in the entity +// TODO: share work with R_SetUpAliasTransform + +// yaw + angle = RI.currententity->angles[YAW]; + angle = angle * M_PI*2 / 360; + s = sin(angle); + c = cos(angle); + + temp1[0][0] = c; + temp1[0][1] = s; + temp1[0][2] = 0; + temp1[1][0] = -s; + temp1[1][1] = c; + temp1[1][2] = 0; + temp1[2][0] = 0; + temp1[2][1] = 0; + temp1[2][2] = 1; + + +// pitch + angle = RI.currententity->angles[PITCH]; + angle = angle * M_PI*2 / 360; + s = sin(angle); + c = cos(angle); + + temp2[0][0] = c; + temp2[0][1] = 0; + temp2[0][2] = -s; + temp2[1][0] = 0; + temp2[1][1] = 1; + temp2[1][2] = 0; + temp2[2][0] = s; + temp2[2][1] = 0; + temp2[2][2] = c; + + R_ConcatRotations (temp2, temp1, temp3); + +// roll + angle = RI.currententity->angles[ROLL]; + angle = angle * M_PI*2 / 360; + s = sin(angle); + c = cos(angle); + + temp1[0][0] = 1; + temp1[0][1] = 0; + temp1[0][2] = 0; + temp1[1][0] = 0; + temp1[1][1] = c; + temp1[1][2] = s; + temp1[2][0] = 0; + temp1[2][1] = -s; + temp1[2][2] = c; + + R_ConcatRotations (temp1, temp3, entity_rotation); + +// +// rotate modelorg and the transformation matrix +// + R_EntityRotate (modelorg); + R_EntityRotate (vpn); + R_EntityRotate (vright); + R_EntityRotate (vup); + + R_TransformFrustum (); +} + + +/* +================ +R_RecursiveClipBPoly + +Clip a bmodel poly down the world bsp tree +================ +*/ +void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) +{ + bedge_t *psideedges[2], *pnextedge, *ptedge; + int i, side, lastside; + float dist, frac, lastdist; + mplane_t *splitplane, tplane; + mvertex_t *pvert, *plastvert, *ptvert; + mnode_t *pn; + int area; + + psideedges[0] = psideedges[1] = NULL; + + makeclippededge = false; + +// transform the BSP plane into model space +// FIXME: cache these? + splitplane = pnode->plane; + tplane.dist = splitplane->dist - + DotProduct(r_entorigin, splitplane->normal); + tplane.normal[0] = DotProduct (entity_rotation[0], splitplane->normal); + tplane.normal[1] = DotProduct (entity_rotation[1], splitplane->normal); + tplane.normal[2] = DotProduct (entity_rotation[2], splitplane->normal); + +// clip edges to BSP plane + for ( ; pedges ; pedges = pnextedge) + { + pnextedge = pedges->pnext; + + // set the status for the last point as the previous point + // FIXME: cache this stuff somehow? + plastvert = pedges->v[0]; + lastdist = DotProduct (plastvert->position, tplane.normal) - + tplane.dist; + + if (lastdist > 0) + lastside = 0; + else + lastside = 1; + + pvert = pedges->v[1]; + + dist = DotProduct (pvert->position, tplane.normal) - tplane.dist; + + if (dist > 0) + side = 0; + else + side = 1; + + if (side != lastside) + { + // clipped + if (numbverts >= MAX_BMODEL_VERTS) + return; + + // generate the clipped vertex + frac = lastdist / (lastdist - dist); + ptvert = &pbverts[numbverts++]; + ptvert->position[0] = plastvert->position[0] + + frac * (pvert->position[0] - + plastvert->position[0]); + ptvert->position[1] = plastvert->position[1] + + frac * (pvert->position[1] - + plastvert->position[1]); + ptvert->position[2] = plastvert->position[2] + + frac * (pvert->position[2] - + plastvert->position[2]); + + // split into two edges, one on each side, and remember entering + // and exiting points + // FIXME: share the clip edge by having a winding direction flag? + if (numbedges >= (MAX_BMODEL_EDGES - 1)) + { + gEngfuncs.Con_Printf ("Out of edges for bmodel\n"); + return; + } + + ptedge = &pbedges[numbedges]; + ptedge->pnext = psideedges[lastside]; + psideedges[lastside] = ptedge; + ptedge->v[0] = plastvert; + ptedge->v[1] = ptvert; + + ptedge = &pbedges[numbedges + 1]; + ptedge->pnext = psideedges[side]; + psideedges[side] = ptedge; + ptedge->v[0] = ptvert; + ptedge->v[1] = pvert; + + numbedges += 2; + + if (side == 0) + { + // entering for front, exiting for back + pfrontenter = ptvert; + makeclippededge = true; + } + else + { + pfrontexit = ptvert; + makeclippededge = true; + } + } + else + { + // add the edge to the appropriate side + pedges->pnext = psideedges[side]; + psideedges[side] = pedges; + } + } + +// if anything was clipped, reconstitute and add the edges along the clip +// plane to both sides (but in opposite directions) + if (makeclippededge) + { + if (numbedges >= (MAX_BMODEL_EDGES - 2)) + { + gEngfuncs.Con_Printf ("Out of edges for bmodel\n"); + return; + } + + ptedge = &pbedges[numbedges]; + ptedge->pnext = psideedges[0]; + psideedges[0] = ptedge; + ptedge->v[0] = pfrontexit; + ptedge->v[1] = pfrontenter; + + ptedge = &pbedges[numbedges + 1]; + ptedge->pnext = psideedges[1]; + psideedges[1] = ptedge; + ptedge->v[0] = pfrontenter; + ptedge->v[1] = pfrontexit; + + numbedges += 2; + } + // draw or recurse further + for (i=0 ; i<2 ; i++) + { + if (psideedges[i]) + { + // draw if we've reached a non-solid leaf, done if all that's left is a + // solid leaf, and continue down the tree if it's not a leaf + pn = pnode->children[i]; + + // we're done with this branch if the node or leaf isn't in the PVS + if (pn->visframe == r_visframecount) + { + if (pn->contents < 0) + { + if (pn->contents != CONTENTS_SOLID) + { + r_currentbkey = ((mleaf_t *)pn)->cluster; + R_RenderBmodelFace (psideedges[i], psurf); + } + } + else + { + R_RecursiveClipBPoly (psideedges[i], pnode->children[i], + psurf); + } + } + } + } + +} + + +/* +================ +R_DrawSolidClippedSubmodelPolygons + +Bmodel crosses multiple leafs +================ +*/ +void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel, mnode_t *topnode) +{ + int i, j, lindex; + vec_t dot; + msurface_t *psurf; + int numsurfaces; + mplane_t *pplane; + mvertex_t bverts[MAX_BMODEL_VERTS]; + bedge_t bedges[MAX_BMODEL_EDGES], *pbedge; + medge_t *pedge, *pedges; + +// FIXME: use bounding-box-based frustum clipping info? + + psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; + numsurfaces = pmodel->nummodelsurfaces; + pedges = pmodel->edges; + + for (i=0 ; iplane; + + dot = DotProduct (modelorg, pplane->normal) - pplane->dist; + + // draw the polygon + if (( !(psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || + ((psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) + continue; + + // FIXME: use bounding-box-based frustum clipping info? + + // copy the edges to bedges, flipping if necessary so always + // clockwise winding + // FIXME: if edges and vertices get caches, these assignments must move + // outside the loop, and overflow checking must be done here + pbverts = bverts; + pbedges = bedges; + numbverts = numbedges = 0; + pbedge = &bedges[numbedges]; + numbedges += psurf->numedges; + + for (j=0 ; jnumedges ; j++) + { + lindex = pmodel->surfedges[psurf->firstedge+j]; + + if (lindex > 0) + { + pedge = &pedges[lindex]; + pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[0]]; + pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[1]]; + } + else + { + lindex = -lindex; + pedge = &pedges[lindex]; + pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[1]]; + pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[0]]; + } + + pbedge[j].pnext = &pbedge[j+1]; + } + + pbedge[j-1].pnext = NULL; // mark end of edges + + //if ( !( psurf->texinfo->flags & ( SURF_TRANS66 | SURF_TRANS33 ) ) ) + R_RecursiveClipBPoly (pbedge, topnode, psurf); + //else + // R_RenderBmodelFace( pbedge, psurf ); + } +} + + +/* +================ +R_DrawSubmodelPolygons + +All in one leaf +================ +*/ +void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags, mnode_t *topnode) +{ + int i; + vec_t dot; + msurface_t *psurf; + int numsurfaces; + mplane_t *pplane; + +// FIXME: use bounding-box-based frustum clipping info? + + psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; + numsurfaces = pmodel->nummodelsurfaces; + + for (i=0 ; iplane; + + dot = DotProduct (modelorg, pplane->normal) - pplane->dist; + + // draw the polygon + if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || + (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) + { + r_currentkey = ((mleaf_t *)topnode)->cluster; + + // FIXME: use bounding-box-based frustum clipping info? + R_RenderFace (psurf, clipflags); + } + } +} + + +int c_drawnode; + +/* +================ +R_RecursiveWorldNode +================ +*/ +void R_RecursiveWorldNode (mnode_t *node, int clipflags) +{ + int i, c, side, *pindex; + vec3_t acceptpt, rejectpt; + mplane_t *plane; + msurface_t *surf, **mark; + mleaf_t *pleaf; + double d, dot; + + if (node->contents == CONTENTS_SOLID) + return; // solid + + if (node->visframe != r_visframecount) + return; + +// cull the clipping planes if not trivial accept +// FIXME: the compiler is doing a lousy job of optimizing here; it could be +// twice as fast in ASM + if (clipflags) + { + for (i=0 ; i<4 ; i++) + { + if (! (clipflags & (1<minmaxs[pindex[0]]; + rejectpt[1] = (float)node->minmaxs[pindex[1]]; + rejectpt[2] = (float)node->minmaxs[pindex[2]]; + + d = DotProduct (rejectpt, view_clipplanes[i].normal); + d -= view_clipplanes[i].dist; + + if (d <= 0) + return; + + acceptpt[0] = (float)node->minmaxs[pindex[3+0]]; + acceptpt[1] = (float)node->minmaxs[pindex[3+1]]; + acceptpt[2] = (float)node->minmaxs[pindex[3+2]]; + + d = DotProduct (acceptpt, view_clipplanes[i].normal); + d -= view_clipplanes[i].dist; + + if (d >= 0) + clipflags &= ~(1<contents < 0) + { + pleaf = (mleaf_t *)node; + + mark = pleaf->firstmarksurface; + c = pleaf->nummarksurfaces; + + if (c) + { + do + { + (*mark)->visframe = r_framecount; + mark++; + } while (--c); + } + + // deal with model fragments in this leaf + if (pleaf->efrags) + { + gEngfuncs.R_StoreEfrags(&pleaf->efrags,tr.realframecount); + } + + pleaf->cluster = r_currentkey; + r_currentkey++; // all bmodels in a leaf share the same key + } + else + { + // node is just a decision point, so go down the apropriate sides + + // find which side of the node we are on + plane = node->plane; + + switch (plane->type) + { + case PLANE_X: + dot = modelorg[0] - plane->dist; + break; + case PLANE_Y: + dot = modelorg[1] - plane->dist; + break; + case PLANE_Z: + dot = modelorg[2] - plane->dist; + break; + default: + dot = DotProduct (modelorg, plane->normal) - plane->dist; + break; + } + + if (dot >= 0) + side = 0; + else + side = 1; + + // recurse down the children, front side first + R_RecursiveWorldNode (node->children[side], clipflags); + + // draw stuff + c = node->numsurfaces; + + if (c) + { + surf = WORLDMODEL->surfaces + node->firstsurface; + + if (dot < -BACKFACE_EPSILON) + { + do + { + if ((surf->flags & SURF_PLANEBACK) && + (surf->visframe == r_framecount)) + { + R_RenderFace (surf, clipflags); + } + + surf++; + } while (--c); + } + else if (dot > BACKFACE_EPSILON) + { + do + { + if (!(surf->flags & SURF_PLANEBACK) && + (surf->visframe == r_framecount)) + { + R_RenderFace (surf, clipflags); + } + + surf++; + } while (--c); + } + + // all surfaces on the same node share the same sequence number + r_currentkey++; + } + + // recurse down the back side + R_RecursiveWorldNode (node->children[!side], clipflags); + } +} + +/* +================ +R_RenderWorld +================ +*/ +void R_RenderWorld (void) +{ + + //if (!r_drawworld->value) + // return; + if ( !RI.drawWorld ) + return; + + c_drawnode=0; + + // auto cycle the world frame for texture animation + RI.currententity = gEngfuncs.GetEntityByIndex(0); + //RI.currententity->frame = (int)(gpGlobals->time*2); + + VectorCopy (r_origin, modelorg); + RI.currentmodel = WORLDMODEL; + r_pcurrentvertbase = RI.currentmodel->vertexes; + + R_RecursiveWorldNode (RI.currentmodel->nodes, 15); +} + + diff --git a/r_context.c b/r_context.c index 7c22764e..48e7b997 100644 --- a/r_context.c +++ b/r_context.c @@ -22,6 +22,10 @@ gl_globals_t tr; ref_speeds_t r_stats; byte *r_temppool; cvar_t *gl_emboss_scale; +cvar_t *r_drawentities; +cvar_t *r_norefresh; +cvar_t *vid_gamma; +cvar_t *vid_brightness; viddef_t vid; static void R_ClearScreen( void ) { @@ -319,7 +323,7 @@ void GL_SetTexCoordArrayMode() { } -void R_InitBlit(); + void GL_OnContextCreated() { R_InitBlit(); @@ -333,30 +337,6 @@ void GL_InitExtensions() void GL_ClearExtensions() { -} -void R_BeginFrame(qboolean clearScene) -{ -} - -void R_RenderScene() -{ - -} - -void R_EndFrame() -{ - // blit pixels with GL until engine supports REF_SOFT context - R_BlitScreen(); -} - -void R_PushScene() -{ - -} - -void R_PopScene() -{ - } void GL_BackendStartFrame() @@ -369,10 +349,6 @@ void GL_BackendEndFrame() } -void R_AllowFog(qboolean allowed) -{ - -} void GL_SetRenderMode(int mode) { @@ -381,12 +357,6 @@ void GL_SetRenderMode(int mode) /// maybe, setup block drawing function pointers here } -qboolean R_AddEntity(struct cl_entity_s *pRefEntity, int entityType) -{ - // no entities support until we draw world... - return false; -} - void CL_AddCustomBeam(cl_entity_t *pEnvBeam) { // same for beams @@ -417,12 +387,6 @@ qboolean VID_CubemapShot(const char *base, uint size, const float *vieworg, qboo // cubemaps? in my softrender??? } -colorVec R_LightPoint(const vec3_t p0) -{ - colorVec c = {0}; - return c; -} - void R_DecalShoot(int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale) { @@ -468,11 +432,6 @@ void GL_SubdivideSurface(msurface_t *fa) } -void CL_RunLightStyles() -{ - -} - void Mod_LoadMapSprite(model_t *mod, const void *buffer, size_t size, qboolean *loaded) { @@ -558,17 +517,6 @@ struct mstudiotex_s *R_StudioGetTexture(cl_entity_t *e) return NULL; } -colorVec R_LightVec(const vec3_t start, const vec3_t end, vec3_t lightspot, vec3_t lightvec) -{ - colorVec v = {0}; - return v; -} - -int R_RenderFrame(const struct ref_viewpass_s *vp) -{ - -} - void GL_BuildLightmaps() { @@ -589,16 +537,6 @@ byte *Mod_GetCurrentVis() return NULL; } -void R_ClearScene() -{ - -} - -void R_NewMap() -{ - -} - void R_ScreenToWorld(const vec3_t screen, vec3_t point) { @@ -617,39 +555,6 @@ void GL_SetupAttributes( int safegl ) gEngfuncs.GL_SetAttribute( REF_GL_BLUE_SIZE, 5 ); } - - - -qboolean R_Init() -{ - gl_emboss_scale = gEngfuncs.Cvar_Get( "gl_emboss_scale", "0", FCVAR_ARCHIVE|FCVAR_LATCH, "fake bumpmapping scale" ); - // create the window and set up the context - r_temppool = Mem_AllocPool( "ref_sw zone" ); - - vid.width = 1920; - vid.height = 1080; - vid.rowbytes = 1920; // rowpixels - - vid.buffer = Mem_Malloc( r_temppool, 1920*1080*sizeof( pixel_t ) ); - if( !gEngfuncs.R_Init_Video( REF_GL )) // request GL context - { - gEngfuncs.R_Free_Video(); - - gEngfuncs.Host_Error( "Can't initialize video subsystem\nProbably driver was not installed" ); - return false; - } - - - R_InitImages(); - return true; -} - -void R_Shutdown() -{ - R_ShutdownImages(); - gEngfuncs.R_Free_Video(); -} - ref_interface_t gReffuncs = { R_Init, diff --git a/r_draw.c b/r_draw.c index 53dd1776..05f4d10b 100644 --- a/r_draw.c +++ b/r_draw.c @@ -151,7 +151,7 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, } else if( alpha < 7) // && (vid.rendermode == kRenderTransAlpha || vid.rendermode == kRenderTransTexture ) ) { - pixel_t screen = dest[u]; + pixel_t screen = dest[u]; // | 0xff & screen & src ; dest[u] = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) >> 3 | ((src & 0xff) >> 3); } @@ -181,6 +181,12 @@ void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, f R_DrawStretchPicImplementation(x,y,w,h, pic->width * s1, pic->height * t1, pic->width * s2, pic->height * t2, pic); } +void Draw_Fill (int x, int y, int w, int h, int c) +{ + // todo: color + R_DrawStretchPicImplementation(x,y,w,h, 0, 0, 12, 1, tr.whiteTexture ); +} + /* ============= Draw_TileClear diff --git a/r_edge.c b/r_edge.c new file mode 100644 index 00000000..ff3984cb --- /dev/null +++ b/r_edge.c @@ -0,0 +1,1132 @@ +/* +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. + +*/ +// r_edge.c + +#include "r_local.h" + +#ifndef id386 +void R_SurfacePatch (void) +{ +} + +void R_EdgeCodeStart (void) +{ +} + +void R_EdgeCodeEnd (void) +{ +} +#endif + + +#if 0 +the complex cases add new polys on most lines, so dont optimize for keeping them the same +have multiple free span lists to try to get better coherence? +low depth complexity -- 1 to 3 or so + +have a sentinal at both ends? +#endif + + +edge_t *auxedges; +edge_t *r_edges, *edge_p, *edge_max; + +surf_t *surfaces, *surface_p, *surf_max; + +// surfaces are generated in back to front order by the bsp, so if a surf +// pointer is greater than another one, it should be drawn in front +// surfaces[1] is the background, and is used as the active surface stack + +edge_t *newedges[MAXHEIGHT]; +edge_t *removeedges[MAXHEIGHT]; + +espan_t *span_p, *max_span_p; + +int r_currentkey; + +int current_iv; + +int edge_head_u_shift20, edge_tail_u_shift20; + +static void (*pdrawfunc)(void); + +edge_t edge_head; +edge_t edge_tail; +edge_t edge_aftertail; +edge_t edge_sentinel; + +float fv; + +static int miplevel; + +float scale_for_mip; +int ubasestep, errorterm, erroradjustup, erroradjustdown; + +// FIXME: should go away +extern void R_RotateBmodel (void); +extern void R_TransformFrustum (void); + + + +void R_GenerateSpans (void); +void R_GenerateSpansBackward (void); + +void R_LeadingEdge (edge_t *edge); +void R_LeadingEdgeBackwards (edge_t *edge); +void R_TrailingEdge (surf_t *surf, edge_t *edge); + + +/* +=============================================================================== + +EDGE SCANNING + +=============================================================================== +*/ + +/* +============== +R_BeginEdgeFrame +============== +*/ +void R_BeginEdgeFrame (void) +{ + int v; + + edge_p = r_edges; + edge_max = &r_edges[r_numallocatededges]; + + surface_p = &surfaces[2]; // background is surface 1, + // surface 0 is a dummy + surfaces[1].spans = NULL; // no background spans yet + surfaces[1].flags = 0; // SURF_DRAWBACKGROUND; + +// put the background behind everything in the world + if (sw_draworder->value) + { + pdrawfunc = R_GenerateSpansBackward; + surfaces[1].key = 0; + r_currentkey = 1; + } + else + { + pdrawfunc = R_GenerateSpans; + surfaces[1].key = 0x7FFfFFFF; + r_currentkey = 0; + } + +// FIXME: set with memset + for (v=0 ; vheight ; v++) + { + newedges[v] = removeedges[v] = NULL; + } +} + + +#if !id386 + +/* +============== +R_InsertNewEdges + +Adds the edges in the linked list edgestoadd, adding them to the edges in the +linked list edgelist. edgestoadd is assumed to be sorted on u, and non-empty (this is actually newedges[v]). edgelist is assumed to be sorted on u, with a +sentinel at the end (actually, this is the active edge table starting at +edge_head.next). +============== +*/ +void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist) +{ + edge_t *next_edge; + + do + { + next_edge = edgestoadd->next; +edgesearch: + if (edgelist->u >= edgestoadd->u) + goto addedge; + edgelist=edgelist->next; + if (edgelist->u >= edgestoadd->u) + goto addedge; + edgelist=edgelist->next; + if (edgelist->u >= edgestoadd->u) + goto addedge; + edgelist=edgelist->next; + if (edgelist->u >= edgestoadd->u) + goto addedge; + edgelist=edgelist->next; + goto edgesearch; + + // insert edgestoadd before edgelist +addedge: + edgestoadd->next = edgelist; + edgestoadd->prev = edgelist->prev; + edgelist->prev->next = edgestoadd; + edgelist->prev = edgestoadd; + } while ((edgestoadd = next_edge) != NULL); +} + +#endif // !id386 + + +#if !id386 + +/* +============== +R_RemoveEdges +============== +*/ +void R_RemoveEdges (edge_t *pedge) +{ + + do + { + pedge->next->prev = pedge->prev; + pedge->prev->next = pedge->next; + } while ((pedge = pedge->nextremove) != NULL); +} + +#endif // !id386 + + +#if !id386 + +/* +============== +R_StepActiveU +============== +*/ +void R_StepActiveU (edge_t *pedge) +{ + edge_t *pnext_edge, *pwedge; + + while (1) + { +nextedge: + pedge->u += pedge->u_step; + if (pedge->u < pedge->prev->u) + goto pushback; + pedge = pedge->next; + + pedge->u += pedge->u_step; + if (pedge->u < pedge->prev->u) + goto pushback; + pedge = pedge->next; + + pedge->u += pedge->u_step; + if (pedge->u < pedge->prev->u) + goto pushback; + pedge = pedge->next; + + pedge->u += pedge->u_step; + if (pedge->u < pedge->prev->u) + goto pushback; + pedge = pedge->next; + + goto nextedge; + +pushback: + if (pedge == &edge_aftertail) + return; + + // push it back to keep it sorted + pnext_edge = pedge->next; + + // pull the edge out of the edge list + pedge->next->prev = pedge->prev; + pedge->prev->next = pedge->next; + + // find out where the edge goes in the edge list + pwedge = pedge->prev->prev; + + while (pwedge->u > pedge->u) + { + pwedge = pwedge->prev; + } + + // put the edge back into the edge list + pedge->next = pwedge->next; + pedge->prev = pwedge; + pedge->next->prev = pedge; + pwedge->next = pedge; + + pedge = pnext_edge; + if (pedge == &edge_tail) + return; + } +} + +#endif // !id386 + + +/* +============== +R_CleanupSpan +============== +*/ +void R_CleanupSpan (void) +{ + surf_t *surf; + int iu; + espan_t *span; + +// now that we've reached the right edge of the screen, we're done with any +// unfinished surfaces, so emit a span for whatever's on top + surf = surfaces[1].next; + iu = edge_tail_u_shift20; + if (iu > surf->last_u) + { + span = span_p++; + span->u = surf->last_u; + span->count = iu - span->u; + span->v = current_iv; + span->pnext = surf->spans; + surf->spans = span; + } + +// reset spanstate for all surfaces in the surface stack + do + { + surf->spanstate = 0; + surf = surf->next; + } while (surf != &surfaces[1]); +} + + +/* +============== +R_LeadingEdgeBackwards +============== +*/ +void R_LeadingEdgeBackwards (edge_t *edge) +{ + espan_t *span; + surf_t *surf, *surf2; + int iu; + +// it's adding a new surface in, so find the correct place + surf = &surfaces[edge->surfs[1]]; + +// don't start a span if this is an inverted span, with the end +// edge preceding the start edge (that is, we've already seen the +// end edge) + if (++surf->spanstate == 1) + { + surf2 = surfaces[1].next; + + if (surf->key > surf2->key) + goto newtop; + + // if it's two surfaces on the same plane, the one that's already + // active is in front, so keep going unless it's a bmodel + if (surf->insubmodel && (surf->key == surf2->key)) + { + // must be two bmodels in the same leaf; don't care, because they'll + // never be farthest anyway + goto newtop; + } + +continue_search: + + do + { + surf2 = surf2->next; + } while (surf->key < surf2->key); + + if (surf->key == surf2->key) + { + // if it's two surfaces on the same plane, the one that's already + // active is in front, so keep going unless it's a bmodel + if (!surf->insubmodel) + goto continue_search; + + // must be two bmodels in the same leaf; don't care which is really + // in front, because they'll never be farthest anyway + } + + goto gotposition; + +newtop: + // emit a span (obscures current top) + iu = edge->u >> 20; + + if (iu > surf2->last_u) + { + span = span_p++; + span->u = surf2->last_u; + span->count = iu - span->u; + span->v = current_iv; + span->pnext = surf2->spans; + surf2->spans = span; + } + + // set last_u on the new span + surf->last_u = iu; + +gotposition: + // insert before surf2 + surf->next = surf2; + surf->prev = surf2->prev; + surf2->prev->next = surf; + surf2->prev = surf; + } +} + + +/* +============== +R_TrailingEdge +============== +*/ +void R_TrailingEdge (surf_t *surf, edge_t *edge) +{ + espan_t *span; + int iu; + +// don't generate a span if this is an inverted span, with the end +// edge preceding the start edge (that is, we haven't seen the +// start edge yet) + if (--surf->spanstate == 0) + { + if (surf == surfaces[1].next) + { + // emit a span (current top going away) + iu = edge->u >> 20; + if (iu > surf->last_u) + { + span = span_p++; + span->u = surf->last_u; + span->count = iu - span->u; + span->v = current_iv; + span->pnext = surf->spans; + surf->spans = span; + } + + // set last_u on the surface below + surf->next->last_u = iu; + } + + surf->prev->next = surf->next; + surf->next->prev = surf->prev; + } +} + + +#if !id386 + +/* +============== +R_LeadingEdge +============== +*/ +void R_LeadingEdge (edge_t *edge) +{ + espan_t *span; + surf_t *surf, *surf2; + int iu; + float fu, newzi, testzi, newzitop, newzibottom; + + if (edge->surfs[1]) + { + // it's adding a new surface in, so find the correct place + surf = &surfaces[edge->surfs[1]]; + + // don't start a span if this is an inverted span, with the end + // edge preceding the start edge (that is, we've already seen the + // end edge) + if (++surf->spanstate == 1) + { + surf2 = surfaces[1].next; + + if (surf->key < surf2->key) + goto newtop; + + // if it's two surfaces on the same plane, the one that's already + // active is in front, so keep going unless it's a bmodel + if (surf->insubmodel && (surf->key == surf2->key)) + { + // must be two bmodels in the same leaf; sort on 1/z + fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000); + newzi = surf->d_ziorigin + fv*surf->d_zistepv + + fu*surf->d_zistepu; + newzibottom = newzi * 0.99; + + testzi = surf2->d_ziorigin + fv*surf2->d_zistepv + + fu*surf2->d_zistepu; + + if (newzibottom >= testzi) + { + goto newtop; + } + + newzitop = newzi * 1.01; + if (newzitop >= testzi) + { + if (surf->d_zistepu >= surf2->d_zistepu) + { + goto newtop; + } + } + } + +continue_search: + + do + { + surf2 = surf2->next; + } while (surf->key > surf2->key); + + if (surf->key == surf2->key) + { + // if it's two surfaces on the same plane, the one that's already + // active is in front, so keep going unless it's a bmodel + if (!surf->insubmodel) + goto continue_search; + + // must be two bmodels in the same leaf; sort on 1/z + fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000); + newzi = surf->d_ziorigin + fv*surf->d_zistepv + + fu*surf->d_zistepu; + newzibottom = newzi * 0.99; + + testzi = surf2->d_ziorigin + fv*surf2->d_zistepv + + fu*surf2->d_zistepu; + + if (newzibottom >= testzi) + { + goto gotposition; + } + + newzitop = newzi * 1.01; + if (newzitop >= testzi) + { + if (surf->d_zistepu >= surf2->d_zistepu) + { + goto gotposition; + } + } + + goto continue_search; + } + + goto gotposition; + +newtop: + // emit a span (obscures current top) + iu = edge->u >> 20; + + if (iu > surf2->last_u) + { + span = span_p++; + span->u = surf2->last_u; + span->count = iu - span->u; + span->v = current_iv; + span->pnext = surf2->spans; + surf2->spans = span; + } + + // set last_u on the new span + surf->last_u = iu; + +gotposition: + // insert before surf2 + surf->next = surf2; + surf->prev = surf2->prev; + surf2->prev->next = surf; + surf2->prev = surf; + } + } +} + + +/* +============== +R_GenerateSpans +============== +*/ +void R_GenerateSpans (void) +{ + edge_t *edge; + surf_t *surf; + +// clear active surfaces to just the background surface + surfaces[1].next = surfaces[1].prev = &surfaces[1]; + surfaces[1].last_u = edge_head_u_shift20; + +// generate spans + for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next) + { + if (edge->surfs[0]) + { + // it has a left surface, so a surface is going away for this span + surf = &surfaces[edge->surfs[0]]; + + R_TrailingEdge (surf, edge); + + if (!edge->surfs[1]) + continue; + } + + R_LeadingEdge (edge); + } + + R_CleanupSpan (); +} + +#endif // !id386 + + +/* +============== +R_GenerateSpansBackward +============== +*/ +void R_GenerateSpansBackward (void) +{ + edge_t *edge; + +// clear active surfaces to just the background surface + surfaces[1].next = surfaces[1].prev = &surfaces[1]; + surfaces[1].last_u = edge_head_u_shift20; + +// generate spans + for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next) + { + if (edge->surfs[0]) + R_TrailingEdge (&surfaces[edge->surfs[0]], edge); + + if (edge->surfs[1]) + R_LeadingEdgeBackwards (edge); + } + + R_CleanupSpan (); +} + + +/* +============== +R_ScanEdges + +Input: +newedges[] array + this has links to edges, which have links to surfaces + +Output: +Each surface has a linked list of its visible spans +============== +*/ +void R_ScanEdges (void) +{ + int iv, bottom; + byte basespans[MAXSPANS*sizeof(espan_t)+CACHE_SIZE]; + espan_t *basespan_p; + surf_t *s; + + basespan_p = (espan_t *) + ((long)(basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); + max_span_p = &basespan_p[MAXSPANS - gpGlobals->width]; + + span_p = basespan_p; + +// clear active edges to just the background edges around the whole screen +// FIXME: most of this only needs to be set up once + edge_head.u = 0; //r_refdef.vrect.x << 20; + edge_head_u_shift20 = edge_head.u >> 20; + edge_head.u_step = 0; + edge_head.prev = NULL; + edge_head.next = &edge_tail; + edge_head.surfs[0] = 0; + edge_head.surfs[1] = 1; + + edge_tail.u = 0xFFFFF; // (r_refdef.vrectright << 20) + 0xFFFFF; + edge_tail_u_shift20 = edge_tail.u >> 20; + edge_tail.u_step = 0; + edge_tail.prev = &edge_head; + edge_tail.next = &edge_aftertail; + edge_tail.surfs[0] = 1; + edge_tail.surfs[1] = 0; + + edge_aftertail.u = -1; // force a move + edge_aftertail.u_step = 0; + edge_aftertail.next = &edge_sentinel; + edge_aftertail.prev = &edge_tail; + +// FIXME: do we need this now that we clamp x in r_draw.c? + edge_sentinel.u = 2000 << 24; // make sure nothing sorts past this + edge_sentinel.prev = &edge_aftertail; + +// +// process all scan lines +// + bottom = gpGlobals->height; //r_refdef.vrectbottom - 1; + + for (iv=0 ; iv max_span_p) + { + D_DrawSurfaces (); + + // clear the surface span pointers + for (s = &surfaces[1] ; sspans = NULL; + + span_p = basespan_p; + } + + if (removeedges[iv]) + R_RemoveEdges (removeedges[iv]); + + if (edge_head.next != &edge_tail) + R_StepActiveU (edge_head.next); + } + +// do the last scan (no need to step or sort or remove on the last scan) + + current_iv = iv; + fv = (float)iv; + +// mark that the head (background start) span is pre-included + surfaces[1].spanstate = 1; + + if (newedges[iv]) + R_InsertNewEdges (newedges[iv], edge_head.next); + + (*pdrawfunc) (); + +// draw whatever's left in the span list + D_DrawSurfaces (); +} + + +/* +========================================================================= + +SURFACE FILLING + +========================================================================= +*/ + +msurface_t *pface; +surfcache_t *pcurrentcache; +vec3_t transformed_modelorg; +vec3_t world_transformed_modelorg; +vec3_t local_modelorg; + +/* +============= +D_MipLevelForScale +============= +*/ +int D_MipLevelForScale (float scale) +{ + int lmiplevel; + + if (scale >= d_scalemip[0] ) + lmiplevel = 0; + else if (scale >= d_scalemip[1] ) + lmiplevel = 1; + else if (scale >= d_scalemip[2] ) + lmiplevel = 2; + else + lmiplevel = 3; + + if (lmiplevel < d_minmip) + lmiplevel = d_minmip; + + return lmiplevel; +} + + +/* +============== +D_FlatFillSurface + +Simple single color fill with no texture mapping +============== +*/ +void D_FlatFillSurface (surf_t *surf, int color) +{ + espan_t *span; + byte *pdest; + int u, u2; + + for (span=surf->spans ; span ; span=span->pnext) + { + pdest = (byte *)d_viewbuffer + r_screenwidth*span->v; + u = span->u; + u2 = span->u + span->count - 1; + for ( ; u <= u2 ; u++) + pdest[u] = color; + } +} + + +/* +============== +D_CalcGradients +============== +*/ +void D_CalcGradients (msurface_t *pface) +{ + mplane_t *pplane; + float mipscale; + vec3_t p_temp1; + vec3_t p_saxis, p_taxis; + float t; + + pplane = pface->plane; + + mipscale = 1.0 / (float)(1 << miplevel); + + TransformVector (pface->texinfo->vecs[0], p_saxis); + TransformVector (pface->texinfo->vecs[1], p_taxis); + + t = xscaleinv * mipscale; + d_sdivzstepu = p_saxis[0] * t; + d_tdivzstepu = p_taxis[0] * t; + + t = yscaleinv * mipscale; + d_sdivzstepv = -p_saxis[1] * t; + d_tdivzstepv = -p_taxis[1] * t; + + d_sdivzorigin = p_saxis[2] * mipscale - xcenter * d_sdivzstepu - + ycenter * d_sdivzstepv; + d_tdivzorigin = p_taxis[2] * mipscale - xcenter * d_tdivzstepu - + ycenter * d_tdivzstepv; + + VectorScale (transformed_modelorg, mipscale, p_temp1); + + t = 0x10000*mipscale; + sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) - + ((pface->texturemins[0] << 16) >> miplevel) + + pface->texinfo->vecs[0][3]*t; + tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - + ((pface->texturemins[1] << 16) >> miplevel) + + pface->texinfo->vecs[1][3]*t; +#if 0 + // PGM - changing flow speed for non-warping textures. + if (pface->texinfo->flags & SURF_FLOWING) + { + if(pface->texinfo->flags & SURF_WARP) + sadjust += 0x10000 * (-128 * ( (r_newrefdef.time * 0.25) - (int)(r_newrefdef.time * 0.25) )); + else + sadjust += 0x10000 * (-128 * ( (r_newrefdef.time * 0.77) - (int)(r_newrefdef.time * 0.77) )); + } + // PGM +#endif +// +// -1 (-epsilon) so we never wander off the edge of the texture +// + bbextents = ((pface->extents[0] << 16) >> miplevel) - 1; + bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1; +} + + +/* +============== +D_BackgroundSurf + +The grey background filler seen when there is a hole in the map +============== +*/ +void D_BackgroundSurf (surf_t *s) +{ +// set up a gradient for the background surface that places it +// effectively at infinity distance from the viewpoint + d_zistepu = 0; + d_zistepv = 0; + d_ziorigin = -0.9; + + D_FlatFillSurface (s, (int)sw_clearcolor->value & 0xFF); + D_DrawZSpans (s->spans); +} + +/* +================= +D_TurbulentSurf +================= +*/ +void D_TurbulentSurf (surf_t *s) +{ + d_zistepu = s->d_zistepu; + d_zistepv = s->d_zistepv; + d_ziorigin = s->d_ziorigin; + + pface = s->msurf; + miplevel = 0; + cacheblock = R_GetTexture(pface->texinfo->texture->gl_texturenum)->pixels[0]; + cachewidth = 64; + + if (s->insubmodel) + { + // FIXME: we don't want to do all this for every polygon! + // TODO: store once at start of frame + RI.currententity = s->entity; //FIXME: make this passed in to + // R_RotateBmodel () + VectorSubtract (RI.vieworg, RI.currententity->origin, + local_modelorg); + TransformVector (local_modelorg, transformed_modelorg); + + R_RotateBmodel (); // FIXME: don't mess with the frustum, + // make entity passed in + } + + D_CalcGradients (pface); + +//============ +//PGM + // textures that aren't warping are just flowing. Use NonTurbulent8 instead +#if 1 + NonTurbulent8 (s->spans); +#else + if(!(pface->texinfo->flags & SURF_DRAWTURB)) + NonTurbulent8 (s->spans); + else + Turbulent8 (s->spans); +#endif +//PGM +//============ + + D_DrawZSpans (s->spans); + + if (s->insubmodel) + { + // + // restore the old drawing state + // FIXME: we don't want to do this every time! + // TODO: speed up + // + RI.currententity = NULL; // &r_worldentity; + VectorCopy (world_transformed_modelorg, + transformed_modelorg); + VectorCopy (base_vpn, vpn); + VectorCopy (base_vup, vup); + VectorCopy (base_vright, vright); + R_TransformFrustum (); + } +} + +/* +============== +D_SkySurf +============== +*/ +void D_SkySurf (surf_t *s) +{ + pface = s->msurf; + miplevel = 0; + if (!pface->texinfo->texture) + return; + cacheblock = R_GetTexture(pface->texinfo->texture->gl_texturenum)->pixels[0]; + cachewidth = 256; + + d_zistepu = s->d_zistepu; + d_zistepv = s->d_zistepv; + d_ziorigin = s->d_ziorigin; + + D_CalcGradients (pface); + + D_DrawSpans16 (s->spans); + +// set up a gradient for the background surface that places it +// effectively at infinity distance from the viewpoint + d_zistepu = 0; + d_zistepv = 0; + d_ziorigin = -0.9; + + D_DrawZSpans (s->spans); +} + +/* +============== +D_SolidSurf + +Normal surface cached, texture mapped surface +============== +*/ +void D_SolidSurf (surf_t *s) +{ + d_zistepu = s->d_zistepu; + d_zistepv = s->d_zistepv; + d_ziorigin = s->d_ziorigin; + + if (s->insubmodel) + { + // FIXME: we don't want to do all this for every polygon! + // TODO: store once at start of frame + RI.currententity = s->entity; //FIXME: make this passed in to + // R_RotateBmodel () + VectorSubtract (RI.vieworg, RI.currententity->origin, local_modelorg); + TransformVector (local_modelorg, transformed_modelorg); + + R_RotateBmodel (); // FIXME: don't mess with the frustum, + // make entity passed in + } + else + RI.currententity = gEngfuncs.GetEntityByIndex(0); //r_worldentity; + + pface = s->msurf; +#if 1 + miplevel = 0; //D_MipLevelForScale(s->nearzi * scale_for_mip * pface->texinfo->mipadjust); +#else + { + float dot; + float normal[3]; + + if ( s->insubmodel ) + { + VectorCopy( pface->plane->normal, normal ); +// TransformVector( pface->plane->normal, normal); + dot = DotProduct( normal, vpn ); + } + else + { + VectorCopy( pface->plane->normal, normal ); + dot = DotProduct( normal, vpn ); + } + + if ( pface->flags & SURF_PLANEBACK ) + dot = -dot; + + if ( dot > 0 ) + printf( "blah" ); + + miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip * pface->texinfo->mipadjust); + } +#endif + +// FIXME: make this passed in to D_CacheSurface + pcurrentcache = D_CacheSurface (pface, miplevel); + + cacheblock = (pixel_t *)pcurrentcache->data; + cachewidth = pcurrentcache->width; + + D_CalcGradients (pface); + + D_DrawSpans16 (s->spans); + + D_DrawZSpans (s->spans); + + if (s->insubmodel) + { + // + // restore the old drawing state + // FIXME: we don't want to do this every time! + // TODO: speed up + // + VectorCopy (world_transformed_modelorg, + transformed_modelorg); + VectorCopy (base_vpn, vpn); + VectorCopy (base_vup, vup); + VectorCopy (base_vright, vright); + R_TransformFrustum (); + RI.currententity = NULL; //&r_worldentity; + } +} + +/* +============= +D_DrawflatSurfaces + +To allow developers to see the polygon carving of the world +============= +*/ +void D_DrawflatSurfaces (void) +{ + surf_t *s; + + for (s = &surfaces[1] ; sspans) + continue; + + d_zistepu = s->d_zistepu; + d_zistepv = s->d_zistepv; + d_ziorigin = s->d_ziorigin; + + // make a stable color for each surface by taking the low + // bits of the msurface pointer + D_FlatFillSurface (s, (int)s->msurf & 0xFF); + D_DrawZSpans (s->spans); + } +} + +/* +============== +D_DrawSurfaces + +Rasterize all the span lists. Guaranteed zero overdraw. +May be called more than once a frame if the surf list overflows (higher res) +============== +*/ +void D_DrawSurfaces (void) +{ + surf_t *s; + +// currententity = NULL; //&r_worldentity; + VectorSubtract (RI.vieworg, vec3_origin, modelorg); + TransformVector (modelorg, transformed_modelorg); + VectorCopy (transformed_modelorg, world_transformed_modelorg); + + if (!sw_drawflat->value) + { + for (s = &surfaces[1] ; sspans) + continue; + + r_drawnpolycount++; +#if 1 + D_SolidSurf (s); +#else + if (! (s->flags & (SURF_DRAWSKYBOX|SURF_DRAWBACKGROUND|SURF_DRAWTURB) ) ) + D_SolidSurf (s); + else if (s->flags & SURF_DRAWSKYBOX) + D_SkySurf (s); + else if (s->flags & SURF_DRAWBACKGROUND) + D_BackgroundSurf (s); + else if (s->flags & SURF_DRAWTURB) + D_TurbulentSurf (s); +#endif + } + } + else + D_DrawflatSurfaces (); + + RI.currententity = NULL; //&r_worldentity; + VectorSubtract (RI.vieworg, vec3_origin, modelorg); + R_TransformFrustum (); +} + diff --git a/r_glblit.c b/r_glblit.c index 434be575..fac3ba30 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -218,5 +218,5 @@ void R_BlitScreen() pglEnd(); pglDisable( GL_TEXTURE_2D ); gEngfuncs.GL_SwapBuffers(); - memset( vid.buffer, 0, vid.width * vid.height * 2 ); +// memset( vid.buffer, 0, vid.width * vid.height * 2 ); } diff --git a/r_light.c b/r_light.c new file mode 100644 index 00000000..7b3e00cf --- /dev/null +++ b/r_light.c @@ -0,0 +1,499 @@ +/* +gl_rlight.c - dynamic and static lights +Copyright (C) 2010 Uncle Mike + +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 3 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. +*/ + +#include "r_local.h" +#include "pm_local.h" +#include "studio.h" +#include "mathlib.h" +#include "ref_params.h" + +//unused, need refactor +unsigned blocklights[1024]; + +/* +============================================================================= + +DYNAMIC LIGHTS + +============================================================================= +*/ +/* +================== +CL_RunLightStyles + +================== +*/ +void CL_RunLightStyles( void ) +{ + int i, k, flight, clight; + float l, lerpfrac, backlerp; + float frametime = (gpGlobals->time - gpGlobals->oldtime); + float scale; + lightstyle_t *ls; + + if( !WORLDMODEL ) return; + + scale = 1; //r_lighting_modulate->value; + + // light animations + // 'm' is normal light, 'a' is no light, 'z' is double bright + for( i = 0; i < MAX_LIGHTSTYLES; i++ ) + { + ls = gEngfuncs.GetLightStyle( i ); + if( !WORLDMODEL->lightdata ) + { + tr.lightstylevalue[i] = 256 * 256; + continue; + } + + if( !gEngfuncs.CL_GetRenderParm( PARAM_GAMEPAUSED, 0 ) && frametime <= 0.1f ) + ls->time += frametime; // evaluate local time + + flight = (int)Q_floor( ls->time * 10 ); + clight = (int)Q_ceil( ls->time * 10 ); + lerpfrac = ( ls->time * 10 ) - flight; + backlerp = 1.0f - lerpfrac; + + if( !ls->length ) + { + tr.lightstylevalue[i] = 256 * scale; + continue; + } + else if( ls->length == 1 ) + { + // single length style so don't bother interpolating + tr.lightstylevalue[i] = ls->map[0] * 22 * scale; + continue; + } + else if( !ls->interp ) // || !CVAR_TO_BOOL( cl_lightstyle_lerping )) + { + tr.lightstylevalue[i] = ls->map[flight%ls->length] * 22 * scale; + continue; + } + + // interpolate animating light + // frame just gone + k = ls->map[flight % ls->length]; + l = (float)( k * 22.0f ) * backlerp; + + // upcoming frame + k = ls->map[clight % ls->length]; + l += (float)( k * 22.0f ) * lerpfrac; + + tr.lightstylevalue[i] = (int)l * scale; + } +} + +/* +============= +R_MarkLights +============= +*/ +void R_MarkLights( dlight_t *light, int bit, mnode_t *node ) +{ + float dist; + msurface_t *surf; + int i; + + if( !node || node->contents < 0 ) + return; + + dist = PlaneDiff( light->origin, node->plane ); + + if( dist > light->radius ) + { + R_MarkLights( light, bit, node->children[0] ); + return; + } + if( dist < -light->radius ) + { + R_MarkLights( light, bit, node->children[1] ); + return; + } + + // mark the polygons + surf = RI.currentmodel->surfaces + node->firstsurface; + + for( i = 0; i < node->numsurfaces; i++, surf++ ) + { + if( !BoundsAndSphereIntersect( surf->info->mins, surf->info->maxs, light->origin, light->radius )) + continue; // no intersection + + if( surf->dlightframe != tr.dlightframecount ) + { + surf->dlightbits = 0; + surf->dlightframe = tr.dlightframecount; + } + surf->dlightbits |= bit; + } + + R_MarkLights( light, bit, node->children[0] ); + R_MarkLights( light, bit, node->children[1] ); +} + +/* +============= +R_PushDlights +============= +*/ +void R_PushDlights( void ) +{ + dlight_t *l; + int i; + + tr.dlightframecount = tr.framecount; + + RI.currententity = gEngfuncs.GetEntityByIndex( 0 ); + RI.currentmodel = RI.currententity->model; + + for( i = 0; i < MAX_DLIGHTS; i++, l++ ) + { + l = gEngfuncs.GetDynamicLight( i ); + + if( l->die < gpGlobals->time || !l->radius ) + continue; + + //if( GL_FrustumCullSphere( &RI.frustum, l->origin, l->radius, 15 )) + //continue; + + R_MarkLights( l, 1<nodes ); + } +} + +/* +============= +R_CountDlights +============= +*/ +int R_CountDlights( void ) +{ + dlight_t *l; + int i, numDlights = 0; + + for( i = 0; i < MAX_DLIGHTS; i++ ) + { + l = gEngfuncs.GetDynamicLight( i ); + + if( l->die < gpGlobals->time || !l->radius ) + continue; + + numDlights++; + } + + return numDlights; +} + +/* +============= +R_CountSurfaceDlights +============= +*/ +int R_CountSurfaceDlights( msurface_t *surf ) +{ + int i, numDlights = 0; + + for( i = 0; i < MAX_DLIGHTS; i++ ) + { + if(!( surf->dlightbits & BIT( i ))) + continue; // not lit by this light + + numDlights++; + } + + return numDlights; +} + +/* +======================================================================= + + AMBIENT LIGHTING + +======================================================================= +*/ +static vec3_t g_trace_lightspot; +static vec3_t g_trace_lightvec; +static float g_trace_fraction; + +/* +================= +R_RecursiveLightPoint +================= +*/ +static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f, float p2f, colorVec *cv, const vec3_t start, const vec3_t end ) +{ + float front, back, frac, midf; + int i, map, side, size; + float ds, dt, s, t; + int sample_size; + color24 *lm, *dm; + mextrasurf_t *info; + msurface_t *surf; + mtexinfo_t *tex; + matrix3x4 tbn; + vec3_t mid; + + // didn't hit anything + if( !node || node->contents < 0 ) + { + cv->r = cv->g = cv->b = cv->a = 0; + return false; + } + + // calculate mid point + front = PlaneDiff( start, node->plane ); + back = PlaneDiff( end, node->plane ); + + side = front < 0; + if(( back < 0 ) == side ) + return R_RecursiveLightPoint( model, node->children[side], p1f, p2f, cv, start, end ); + + frac = front / ( front - back ); + + VectorLerp( start, frac, end, mid ); + midf = p1f + ( p2f - p1f ) * frac; + + // co down front side + if( R_RecursiveLightPoint( model, node->children[side], p1f, midf, cv, start, mid )) + return true; // hit something + + if(( back < 0 ) == side ) + { + cv->r = cv->g = cv->b = cv->a = 0; + return false; // didn't hit anything + } + + // check for impact on this node + surf = model->surfaces + node->firstsurface; + VectorCopy( mid, g_trace_lightspot ); + + for( i = 0; i < node->numsurfaces; i++, surf++ ) + { + int smax, tmax; + + tex = surf->texinfo; + info = surf->info; + + if( FBitSet( surf->flags, SURF_DRAWTILED )) + continue; // no lightmaps + + s = DotProduct( mid, info->lmvecs[0] ) + info->lmvecs[0][3]; + t = DotProduct( mid, info->lmvecs[1] ) + info->lmvecs[1][3]; + + if( s < info->lightmapmins[0] || t < info->lightmapmins[1] ) + continue; + + ds = s - info->lightmapmins[0]; + dt = t - info->lightmapmins[1]; + + if ( ds > info->lightextents[0] || dt > info->lightextents[1] ) + continue; + + cv->r = cv->g = cv->b = cv->a = 0; + + if( !surf->samples ) + return true; + + sample_size = gEngfuncs.Mod_SampleSizeForFace( surf ); + smax = (info->lightextents[0] / sample_size) + 1; + tmax = (info->lightextents[1] / sample_size) + 1; + ds /= sample_size; + dt /= sample_size; + + lm = surf->samples + Q_rint( dt ) * smax + Q_rint( ds ); + g_trace_fraction = midf; + size = smax * tmax; + dm = NULL; + + if( surf->info->deluxemap ) + { + vec3_t faceNormal; + + if( FBitSet( surf->flags, SURF_PLANEBACK )) + VectorNegate( surf->plane->normal, faceNormal ); + else VectorCopy( surf->plane->normal, faceNormal ); + + // compute face TBN +#if 1 + Vector4Set( tbn[0], surf->info->lmvecs[0][0], surf->info->lmvecs[0][1], surf->info->lmvecs[0][2], 0.0f ); + Vector4Set( tbn[1], -surf->info->lmvecs[1][0], -surf->info->lmvecs[1][1], -surf->info->lmvecs[1][2], 0.0f ); + Vector4Set( tbn[2], faceNormal[0], faceNormal[1], faceNormal[2], 0.0f ); +#else + Vector4Set( tbn[0], surf->info->lmvecs[0][0], -surf->info->lmvecs[1][0], faceNormal[0], 0.0f ); + Vector4Set( tbn[1], surf->info->lmvecs[0][1], -surf->info->lmvecs[1][1], faceNormal[1], 0.0f ); + Vector4Set( tbn[2], surf->info->lmvecs[0][2], -surf->info->lmvecs[1][2], faceNormal[2], 0.0f ); +#endif + VectorNormalize( tbn[0] ); + VectorNormalize( tbn[1] ); + VectorNormalize( tbn[2] ); + dm = surf->info->deluxemap + Q_rint( dt ) * smax + Q_rint( ds ); + } + + for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255; map++ ) + { + uint scale = tr.lightstylevalue[surf->styles[map]]; + + if( tr.ignore_lightgamma ) + { + cv->r += lm->r * scale; + cv->g += lm->g * scale; + cv->b += lm->b * scale; + } + else + { + cv->r += gEngfuncs.LightToTexGamma( lm->r ) * scale; + cv->g += gEngfuncs.LightToTexGamma( lm->g ) * scale; + cv->b += gEngfuncs.LightToTexGamma( lm->b ) * scale; + } + lm += size; // skip to next lightmap + + if( dm != NULL ) + { + vec3_t srcNormal, lightNormal; + float f = (1.0f / 128.0f); + + VectorSet( srcNormal, ((float)dm->r - 128.0f) * f, ((float)dm->g - 128.0f) * f, ((float)dm->b - 128.0f) * f ); + Matrix3x4_VectorIRotate( tbn, srcNormal, lightNormal ); // turn to world space + VectorScale( lightNormal, (float)scale * -1.0f, lightNormal ); // turn direction from light + VectorAdd( g_trace_lightvec, lightNormal, g_trace_lightvec ); + dm += size; // skip to next deluxmap + } + } + + return true; + } + + // go down back side + return R_RecursiveLightPoint( model, node->children[!side], midf, p2f, cv, mid, end ); +} + +/* +================= +R_LightVec + +check bspmodels to get light from +================= +*/ +colorVec R_LightVecInternal( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t lvec ) +{ + float last_fraction; + int i, maxEnts = 1; + colorVec light, cv; + + if( lspot ) VectorClear( lspot ); + if( lvec ) VectorClear( lvec ); + + if( WORLDMODEL && WORLDMODEL->lightdata ) + { + light.r = light.g = light.b = light.a = 0; + last_fraction = 1.0f; + + // get light from bmodels too + //if( CVAR_TO_BOOL( r_lighting_extended )) + maxEnts = MAX_PHYSENTS; + + // check all the bsp-models + for( i = 0; i < maxEnts; i++ ) + { + physent_t *pe = gEngfuncs.EV_GetPhysent( i ); + vec3_t offset, start_l, end_l; + mnode_t *pnodes; + matrix4x4 matrix; + + if( !pe ) + break; + + if( !pe->model || pe->model->type != mod_brush ) + continue; // skip non-bsp models + + pnodes = &pe->model->nodes[pe->model->hulls[0].firstclipnode]; + VectorSubtract( pe->model->hulls[0].clip_mins, vec3_origin, offset ); + VectorAdd( offset, pe->origin, offset ); + VectorSubtract( start, offset, start_l ); + VectorSubtract( end, offset, end_l ); + + // rotate start and end into the models frame of reference + if( !VectorIsNull( pe->angles )) + { + Matrix4x4_CreateFromEntity( matrix, pe->angles, offset, 1.0f ); + Matrix4x4_VectorITransform( matrix, start, start_l ); + Matrix4x4_VectorITransform( matrix, end, end_l ); + } + + VectorClear( g_trace_lightspot ); + VectorClear( g_trace_lightvec ); + g_trace_fraction = 1.0f; + + if( !R_RecursiveLightPoint( pe->model, pnodes, 0.0f, 1.0f, &cv, start_l, end_l )) + continue; // didn't hit anything + + if( g_trace_fraction < last_fraction ) + { + if( lspot ) VectorCopy( g_trace_lightspot, lspot ); + if( lvec ) VectorNormalize2( g_trace_lightvec, lvec ); + light.r = Q_min(( cv.r >> 7 ), 255 ); + light.g = Q_min(( cv.g >> 7 ), 255 ); + light.b = Q_min(( cv.b >> 7 ), 255 ); + last_fraction = g_trace_fraction; + + if(( light.r + light.g + light.b ) != 0 ) + break; // we get light now + } + } + } + else + { + light.r = light.g = light.b = 255; + light.a = 0; + } + + return light; +} + +/* +================= +R_LightVec + +check bspmodels to get light from +================= +*/ +colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t lvec ) +{ + colorVec light = R_LightVecInternal( start, end, lspot, lvec ); + + if( lspot != NULL && lvec != NULL ) // CVAR_TO_BOOL( r_lighting_extended ) && + { + // trying to get light from ceiling (but ignore gradient analyze) + if(( light.r + light.g + light.b ) == 0 ) + return R_LightVecInternal( end, start, lspot, lvec ); + } + + return light; +} + +/* +================= +R_LightPoint + +light from floor +================= +*/ +colorVec R_LightPoint( const vec3_t p0 ) +{ + vec3_t p1; + + VectorSet( p1, p0[0], p0[1], p0[2] - 2048.0f ); + + return R_LightVec( p0, p1, NULL, NULL ); +} diff --git a/r_local.h b/r_local.h index 1cc2262e..8d0eaad0 100644 --- a/r_local.h +++ b/r_local.h @@ -32,6 +32,10 @@ GNU General Public License for more details. #include "pm_movevars.h" //#include "cvar.h" typedef struct mip_s mip_t; + +typedef int fixed8_t; +typedef int fixed16_t; + #define offsetof(s,m) (size_t)&(((s *)0)->m) #define ASSERT(x) if(!( x )) gEngfuncs.Host_Error( "assert failed at %s:%i\n", __FILE__, __LINE__ ) @@ -426,7 +430,7 @@ void R_InitDlightTexture( void ); void R_TextureList_f( void ); void R_InitImages( void ); void R_ShutdownImages( void ); -#if 0 +#if 1 // // gl_rlight.c // @@ -439,7 +443,7 @@ colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lightspot, vec int R_CountSurfaceDlights( msurface_t *surf ); colorVec R_LightPoint( const vec3_t p0 ); int R_CountDlights( void ); - +#endif // // gl_rmain.c // @@ -457,7 +461,7 @@ void R_FindViewLeaf( void ); void R_PushScene( void ); void R_PopScene( void ); void R_DrawFog( void ); - +#if 0 // // gl_rmath.c // @@ -610,8 +614,8 @@ void Mod_SpriteUnloadTextures( void *data ); void Mod_UnloadAliasModel( struct model_s *mod ); void Mod_AliasUnloadTextures( void *data ); void GL_SetRenderMode( int mode ); -void R_RunViewmodelEvents( void ); -void R_DrawViewModel( void ); +//void R_RunViewmodelEvents( void ); +//void R_DrawViewModel( void ); int R_GetSpriteTexture( const struct model_s *m_pSpriteModel, int frame ); void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale ); void R_RemoveEfrags( struct cl_entity_s *ent ); @@ -654,9 +658,20 @@ void TriFogParams( float flDensity, int iFogSkybox ); void TriCullFace( TRICULLSTYLE mode ); +// +// r_blitscreen.c +// +void R_BlitScreen(); +void R_InitBlit(); + + extern ref_api_t gEngfuncs; extern ref_globals_t *gpGlobals; extern cvar_t *gl_emboss_scale; +extern cvar_t *r_drawentities; +extern cvar_t *vid_brightness; +extern cvar_t *vid_gamma; +extern cvar_t *r_norefresh; #if 0 // // renderer cvars @@ -682,7 +697,6 @@ extern cvar_t *gl_stencilbits; extern cvar_t *r_speeds; extern cvar_t *r_fullbright; -extern cvar_t *r_norefresh; extern cvar_t *r_showtree; // build graph of visible hull extern cvar_t *r_lighting_extended; extern cvar_t *r_lighting_modulate; @@ -715,6 +729,496 @@ extern cvar_t *traceralpha; extern cvar_t *cl_lightstyle_lerping; extern cvar_t *r_showhull; #endif +// softrender defs + +#define CACHE_SIZE 32 + +/* +==================================================== + CONSTANTS +==================================================== +*/ + +#define VID_CBITS 6 +#define VID_GRADES (1 << VID_CBITS) + + +// r_shared.h: general refresh-related stuff shared between the refresh and the +// driver + + +#define MAXVERTS 64 // max points in a surface polygon +#define MAXWORKINGVERTS (MAXVERTS+4) // max points in an intermediate + // polygon (while processing) +// !!! if this is changed, it must be changed in d_ifacea.h too !!! +#define MAXHEIGHT 1200 +#define MAXWIDTH 1600 + +#define INFINITE_DISTANCE 0x10000 // distance that's always guaranteed to + // be farther away than anything in + // the scene + + +// d_iface.h: interface header file for rasterization driver modules + +#define WARP_WIDTH 320 +#define WARP_HEIGHT 240 + +#define MAX_LBM_HEIGHT 480 + + +#define PARTICLE_Z_CLIP 8.0 + +// !!! must be kept the same as in quakeasm.h !!! +#define TRANSPARENT_COLOR 0xFF + + +// !!! if this is changed, it must be changed in d_ifacea.h too !!! +#define TURB_TEX_SIZE 64 // base turbulent texture size + +// !!! if this is changed, it must be changed in d_ifacea.h too !!! +#define CYCLE 128 // turbulent cycle size + +#define SCANBUFFERPAD 0x1000 + +#define DS_SPAN_LIST_END -128 + +#define NUMSTACKEDGES 2000 +#define MINEDGES NUMSTACKEDGES +#define NUMSTACKSURFACES 1000 +#define MINSURFACES NUMSTACKSURFACES +#define MAXSPANS 3000 + +// flags in finalvert_t.flags +#define ALIAS_LEFT_CLIP 0x0001 +#define ALIAS_TOP_CLIP 0x0002 +#define ALIAS_RIGHT_CLIP 0x0004 +#define ALIAS_BOTTOM_CLIP 0x0008 +#define ALIAS_Z_CLIP 0x0010 +#define ALIAS_XY_CLIP_MASK 0x000F + +#define SURFCACHE_SIZE_AT_320X240 1024*768 + +#define BMODEL_FULLY_CLIPPED 0x10 // value returned by R_BmodelCheckBBox () + // if bbox is trivially rejected + +#define XCENTERING (1.0 / 2.0) +#define YCENTERING (1.0 / 2.0) + +#define CLIP_EPSILON 0.001 + +#define BACKFACE_EPSILON 0.01 + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +#define NEAR_CLIP 0.01 + + +#define MAXALIASVERTS 2000 // TODO: tune this +#define ALIAS_Z_CLIP_PLANE 4 + +// turbulence stuff + +#define AMP 8*0x10000 +#define AMP2 3 +#define SPEED 20 + + +/* +==================================================== +TYPES +==================================================== +*/ + +typedef struct +{ + float u, v; + float s, t; + float zi; +} emitpoint_t; + +/* +** if you change this structure be sure to change the #defines +** listed after it! +*/ +#define SMALL_FINALVERT 0 + +#if SMALL_FINALVERT + +typedef struct finalvert_s { + short u, v, s, t; + int l; + int zi; + int flags; + float xyz[3]; // eye space +} finalvert_t; + +#define FINALVERT_V0 0 +#define FINALVERT_V1 2 +#define FINALVERT_V2 4 +#define FINALVERT_V3 6 +#define FINALVERT_V4 8 +#define FINALVERT_V5 12 +#define FINALVERT_FLAGS 16 +#define FINALVERT_X 20 +#define FINALVERT_Y 24 +#define FINALVERT_Z 28 +#define FINALVERT_SIZE 32 + +#else + +typedef struct finalvert_s { + int u, v, s, t; + int l; + int zi; + int flags; + float xyz[3]; // eye space +} finalvert_t; + +#define FINALVERT_V0 0 +#define FINALVERT_V1 4 +#define FINALVERT_V2 8 +#define FINALVERT_V3 12 +#define FINALVERT_V4 16 +#define FINALVERT_V5 20 +#define FINALVERT_FLAGS 24 +#define FINALVERT_X 28 +#define FINALVERT_Y 32 +#define FINALVERT_Z 36 +#define FINALVERT_SIZE 40 + +#endif + + +typedef struct +{ + short s; + short t; +} dstvert_t; + +typedef struct +{ + short index_xyz[3]; + short index_st[3]; +} dtriangle_t; + +typedef struct +{ + byte v[3]; // scaled byte to fit in frame mins/maxs + byte lightnormalindex; +} dtrivertx_t; + +#define DTRIVERTX_V0 0 +#define DTRIVERTX_V1 1 +#define DTRIVERTX_V2 2 +#define DTRIVERTX_LNI 3 +#define DTRIVERTX_SIZE 4 + +typedef struct +{ + void *pskin; + int pskindesc; + int skinwidth; + int skinheight; + dtriangle_t *ptriangles; + finalvert_t *pfinalverts; + int numtriangles; + int drawtype; + int seamfixupX16; + qboolean do_vis_thresh; + int vis_thresh; +} affinetridesc_t; + + + +typedef struct +{ + byte *surfdat; // destination for generated surface + int rowbytes; // destination logical width in bytes + msurface_t *surf; // description for surface to generate + fixed8_t lightadj[MAXLIGHTMAPS]; + // adjust for lightmap levels for dynamic lighting + image_t *image; + int surfmip; // mipmapped ratio of surface texels / world pixels + int surfwidth; // in mipmapped texels + int surfheight; // in mipmapped texels +} drawsurf_t; + + +#if 0 +typedef struct { + int ambientlight; + int shadelight; + float *plightvec; +} alight_t; + +#endif + +// clipped bmodel edges + +typedef struct bedge_s +{ + mvertex_t *v[2]; + struct bedge_s *pnext; +} bedge_t; + + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct clipplane_s +{ + vec3_t normal; + float dist; + struct clipplane_s *next; + byte leftedge; + byte rightedge; + byte reserved[2]; +} clipplane_t; + + +typedef struct surfcache_s +{ + struct surfcache_s *next; + struct surfcache_s **owner; // NULL is an empty chunk of memory + int lightadj[MAXLIGHTMAPS]; // checked for strobe flush + int dlight; + int size; // including header + unsigned width; + unsigned height; // DEBUG only needed for debug + float mipscale; + image_t *image; + byte data[4]; // width*height elements +} surfcache_t; + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct espan_s +{ + int u, v, count; + struct espan_s *pnext; +} espan_t; + +// used by the polygon drawer (R_POLY.C) and sprite setup code (R_SPRITE.C) +typedef struct +{ + int nump; + emitpoint_t *pverts; + byte *pixels; // image + int pixel_width; // image width + int pixel_height; // image height + vec3_t vup, vright, vpn; // in worldspace, for plane eq + float dist; + float s_offset, t_offset; + float viewer_position[3]; + void (*drawspanlet)( void ); + int stipple_parity; +} polydesc_t; + +// FIXME: compress, make a union if that will help +// insubmodel is only 1, flags is fewer than 32, spanstate could be a byte +typedef struct surf_s +{ + struct surf_s *next; // active surface stack in r_edge.c + struct surf_s *prev; // used in r_edge.c for active surf stack + struct espan_s *spans; // pointer to linked list of spans to draw + int key; // sorting key (BSP order) + int last_u; // set during tracing + int spanstate; // 0 = not in span + // 1 = in span + // -1 = in inverted span (end before + // start) + int flags; // currentface flags + msurface_t *msurf; + cl_entity_t *entity; + float nearzi; // nearest 1/z on surface, for mipmapping + qboolean insubmodel; + float d_ziorigin, d_zistepu, d_zistepv; + + int pad[2]; // to 64 bytes +} surf_t; + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct edge_s +{ + fixed16_t u; + fixed16_t u_step; + struct edge_s *prev, *next; + unsigned short surfs[2]; + struct edge_s *nextremove; + float nearzi; + medge_t *owner; +} edge_t; + + +/* +==================================================== +VARS +==================================================== +*/ + +extern int d_spanpixcount; +extern int r_framecount; // sequence # of current frame since Quake + // started +extern float r_aliasuvscale; // scale-up factor for screen u and v + // on Alias vertices passed to driver +extern qboolean r_dowarp; + +extern affinetridesc_t r_affinetridesc; + +extern vec3_t r_pright, r_pup, r_ppn; + +void D_DrawSurfaces (void); +void R_DrawParticle( void ); +void D_ViewChanged (void); +void D_WarpScreen (void); +void R_PolysetUpdateTables (void); + +extern void *acolormap; // FIXME: should go away + +//=======================================================================// + +// callbacks to Quake + +extern drawsurf_t r_drawsurf; + +void R_DrawSurface (void); + +extern int c_surf; + +extern byte r_warpbuffer[WARP_WIDTH * WARP_HEIGHT]; + + + + +extern float scale_for_mip; + +extern qboolean d_roverwrapped; +extern surfcache_t *sc_rover; +extern surfcache_t *d_initial_rover; + +extern float d_sdivzstepu, d_tdivzstepu, d_zistepu; +extern float d_sdivzstepv, d_tdivzstepv, d_zistepv; +extern float d_sdivzorigin, d_tdivzorigin, d_ziorigin; + +extern fixed16_t sadjust, tadjust; +extern fixed16_t bbextents, bbextentt; + + +void D_DrawSpans16 (espan_t *pspans); +void D_DrawZSpans (espan_t *pspans); +void Turbulent8 (espan_t *pspan); +void NonTurbulent8 (espan_t *pspan); //PGM + +surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel); + +extern int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle; + +extern int d_pix_min, d_pix_max, d_pix_shift; + +extern pixel_t *d_viewbuffer; +extern short *d_pzbuffer; +extern unsigned int d_zrowbytes, d_zwidth; +extern short *zspantable[MAXHEIGHT]; +extern int d_scantable[MAXHEIGHT]; + +extern int d_minmip; +extern float d_scalemip[3]; + +//=================================================================== + +extern int cachewidth; +extern pixel_t *cacheblock; +extern int r_screenwidth; + +extern int r_drawnpolycount; + +extern int sintable[1280]; +extern int intsintable[1280]; +extern int blanktable[1280]; // PGM + +extern vec3_t vup, base_vup; +extern vec3_t vpn, base_vpn; +extern vec3_t vright, base_vright; + +extern surf_t *surfaces, *surface_p, *surf_max; + +// surfaces are generated in back to front order by the bsp, so if a surf +// pointer is greater than another one, it should be drawn in front +// surfaces[1] is the background, and is used as the active surface stack. +// surfaces[0] is a dummy, because index 0 is used to indicate no surface +// attached to an edge_t + +//=================================================================== + +extern vec3_t sxformaxis[4]; // s axis transformed into viewspace +extern vec3_t txformaxis[4]; // t axis transformed into viewspac + +extern float xcenter, ycenter; +extern float xscale, yscale; +extern float xscaleinv, yscaleinv; +extern float xscaleshrink, yscaleshrink; + + +extern edge_t *auxedges; +extern int r_numallocatededges; +extern edge_t *r_edges, *edge_p, *edge_max; + +extern edge_t *newedges[MAXHEIGHT]; +extern edge_t *removeedges[MAXHEIGHT]; + +// FIXME: make stack vars when debugging done +extern edge_t edge_head; +extern edge_t edge_tail; +extern edge_t edge_aftertail; + + +extern int r_frustum_indexes[4*6]; +extern int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs; +extern qboolean r_surfsonstack; + +extern mleaf_t *r_viewleaf; +extern int r_viewcluster, r_oldviewcluster; + +extern int r_clipflags; +extern int r_dlightframecount; +extern qboolean r_fov_greater_than_90; + + +extern cvar_t *sw_aliasstats; +extern cvar_t *sw_clearcolor; +extern cvar_t *sw_drawflat; +extern cvar_t *sw_draworder; +extern cvar_t *sw_maxedges; +extern cvar_t *sw_maxsurfs; +extern cvar_t *sw_mipcap; +extern cvar_t *sw_mipscale; +extern cvar_t *sw_mode; +extern cvar_t *sw_reportsurfout; +extern cvar_t *sw_reportedgeout; +extern cvar_t *sw_stipplealpha; +extern cvar_t *sw_surfcacheoverride; +extern cvar_t *sw_waterwarp; + +extern vec3_t modelorg; +extern vec3_t r_origin; +extern mplane_t screenedge[4]; + + +extern clipplane_t view_clipplanes[4]; +extern int *pfrustum_indexes[4]; + +extern vec3_t vup, base_vup; +extern vec3_t vpn, base_vpn; +extern vec3_t vright, base_vright; + +extern cvar_t *r_fullbright; + +#define CACHESPOT(surf) ((surfcache_t**)surf->info->reserved) +extern int r_visframecount; +extern mvertex_t *r_pcurrentvertbase; +extern int r_maxvalidedgeoffset; +extern int r_currentkey; +extern int r_currentbkey; + + + // // engine callbacks // diff --git a/r_main.c b/r_main.c new file mode 100644 index 00000000..089ba850 --- /dev/null +++ b/r_main.c @@ -0,0 +1,1576 @@ +/* +gl_rmain.c - renderer main loop +Copyright (C) 2010 Uncle Mike + +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 3 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. +*/ + +#include "r_local.h" +#include "mathlib.h" +#include "library.h" +//#include "beamdef.h" +//#include "particledef.h" +#include "entity_types.h" + +#define IsLiquidContents( cnt ) ( cnt == CONTENTS_WATER || cnt == CONTENTS_SLIME || cnt == CONTENTS_LAVA ) + +float gldepthmin, gldepthmax; +ref_instance_t RI; + + +// quake defines. will be refactored + +// view origin +// +vec3_t vup, base_vup; +vec3_t vpn, base_vpn; +vec3_t vright, base_vright; +vec3_t r_origin; + +// +// screen size info +// +float xcenter, ycenter; +float xscale, yscale; +float xscaleinv, yscaleinv; +float xscaleshrink, yscaleshrink; +float aliasxscale, aliasyscale, aliasxcenter, aliasycenter; + +int r_screenwidth; + +float verticalFieldOfView; +float xOrigin, yOrigin; + +mplane_t screenedge[4]; + + +// +// refresh flags +// +int r_framecount = 1; // so frame counts initialized to 0 don't match +int r_visframecount; +int d_spanpixcount; +int r_polycount; +int r_drawnpolycount; +int r_wholepolycount; + +int *pfrustum_indexes[4]; +int r_frustum_indexes[4*6]; + +mleaf_t *r_viewleaf; +int r_viewcluster, r_oldviewcluster; + +cvar_t *r_lefthand; +cvar_t *sw_aliasstats; +cvar_t *sw_allow_modex; +cvar_t *sw_clearcolor; +cvar_t *sw_drawflat; +cvar_t *sw_draworder; +cvar_t *sw_maxedges; +cvar_t *sw_maxsurfs; +cvar_t *sw_mode; +cvar_t *sw_reportedgeout; +cvar_t *sw_reportsurfout; +cvar_t *sw_stipplealpha; +cvar_t *sw_surfcacheoverride; +cvar_t *sw_waterwarp; + +cvar_t *r_drawworld; +cvar_t *r_drawentities; +cvar_t *r_dspeeds; +cvar_t *r_fullbright; +cvar_t *r_lerpmodels; +cvar_t *r_novis; + +cvar_t *r_speeds; +cvar_t *r_lightlevel; //FIXME HACK + +cvar_t *vid_fullscreen; +cvar_t *vid_gamma; + +//PGM +cvar_t *sw_lockpvs; +//PGM + + +mleaf_t *r_viewleaf; +int r_viewcluster, r_oldviewcluster; + +float d_sdivzstepu, d_tdivzstepu, d_zistepu; +float d_sdivzstepv, d_tdivzstepv, d_zistepv; +float d_sdivzorigin, d_tdivzorigin, d_ziorigin; + +fixed16_t sadjust, tadjust, bbextents, bbextentt; + +pixel_t *cacheblock; +int cachewidth; +pixel_t *d_viewbuffer; +short *d_pzbuffer; +unsigned int d_zrowbytes; +unsigned int d_zwidth; + +qboolean r_dowarp; + +mvertex_t *r_pcurrentvertbase; + +int c_surf; +int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs; +qboolean r_surfsonstack; +int r_clipflags; +byte r_warpbuffer[WARP_WIDTH * WARP_HEIGHT]; +int r_numallocatededges; + + +/* +================ +R_ConcatRotations +================ +*/ +void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]) +{ + out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + + in1[0][2] * in2[2][0]; + out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + + in1[0][2] * in2[2][1]; + out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + + in1[0][2] * in2[2][2]; + out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + + in1[1][2] * in2[2][0]; + out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + + in1[1][2] * in2[2][1]; + out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + + in1[1][2] * in2[2][2]; + out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + + in1[2][2] * in2[2][0]; + out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + + in1[2][2] * in2[2][1]; + out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + + in1[2][2] * in2[2][2]; +} + + + +static int R_RankForRenderMode( int rendermode ) +{ + switch( rendermode ) + { + case kRenderTransTexture: + return 1; // draw second + case kRenderTransAdd: + return 2; // draw third + case kRenderGlow: + return 3; // must be last! + } + return 0; +} + +/* +================ +R_GetEntityRenderMode + +check for texture flags +================ +*/ +int R_GetEntityRenderMode( cl_entity_t *ent ) +{ + int i, opaque, trans; + mstudiotexture_t *ptexture; + cl_entity_t *oldent; + model_t *model; + studiohdr_t *phdr; + + oldent = RI.currententity; + RI.currententity = ent; + return ent->curstate.rendermode; +} + + +void R_AllowFog( qboolean allowed ) +{ +} + +/* +=============== +R_OpaqueEntity + +Opaque entity can be brush or studio model but sprite +=============== +*/ +static qboolean R_OpaqueEntity( cl_entity_t *ent ) +{ + if( R_GetEntityRenderMode( ent ) == kRenderNormal ) + return true; + return false; +} + +/* +=============== +R_TransEntityCompare + +Sorting translucent entities by rendermode then by distance +=============== +*/ +static int R_TransEntityCompare( const cl_entity_t **a, const cl_entity_t **b ) +{ + cl_entity_t *ent1, *ent2; + vec3_t vecLen, org; + float dist1, dist2; + int rendermode1; + int rendermode2; + + ent1 = (cl_entity_t *)*a; + ent2 = (cl_entity_t *)*b; + rendermode1 = R_GetEntityRenderMode( ent1 ); + rendermode2 = R_GetEntityRenderMode( ent2 ); + + // sort by distance + if( ent1->model->type != mod_brush || rendermode1 != kRenderTransAlpha ) + { + VectorAverage( ent1->model->mins, ent1->model->maxs, org ); + VectorAdd( ent1->origin, org, org ); + VectorSubtract( RI.vieworg, org, vecLen ); + dist1 = DotProduct( vecLen, vecLen ); + } + else dist1 = 1000000000; + + if( ent2->model->type != mod_brush || rendermode2 != kRenderTransAlpha ) + { + VectorAverage( ent2->model->mins, ent2->model->maxs, org ); + VectorAdd( ent2->origin, org, org ); + VectorSubtract( RI.vieworg, org, vecLen ); + dist2 = DotProduct( vecLen, vecLen ); + } + else dist2 = 1000000000; + + if( dist1 > dist2 ) + return -1; + if( dist1 < dist2 ) + return 1; + + // then sort by rendermode + if( R_RankForRenderMode( rendermode1 ) > R_RankForRenderMode( rendermode2 )) + return 1; + if( R_RankForRenderMode( rendermode1 ) < R_RankForRenderMode( rendermode2 )) + return -1; + + return 0; +} + +#if 0 + +/* +=============== +R_WorldToScreen + +Convert a given point from world into screen space +Returns true if we behind to screen +=============== +*/ +int R_WorldToScreen( const vec3_t point, vec3_t screen ) +{ + matrix4x4 worldToScreen; + qboolean behind; + float w; + + if( !point || !screen ) + return true; + + Matrix4x4_Copy( worldToScreen, RI.worldviewProjectionMatrix ); + screen[0] = worldToScreen[0][0] * point[0] + worldToScreen[0][1] * point[1] + worldToScreen[0][2] * point[2] + worldToScreen[0][3]; + screen[1] = worldToScreen[1][0] * point[0] + worldToScreen[1][1] * point[1] + worldToScreen[1][2] * point[2] + worldToScreen[1][3]; + w = worldToScreen[3][0] * point[0] + worldToScreen[3][1] * point[1] + worldToScreen[3][2] * point[2] + worldToScreen[3][3]; + screen[2] = 0.0f; // just so we have something valid here + + if( w < 0.001f ) + { + screen[0] *= 100000; + screen[1] *= 100000; + behind = true; + } + else + { + float invw = 1.0f / w; + screen[0] *= invw; + screen[1] *= invw; + behind = false; + } + + return behind; +} + +/* +=============== +R_ScreenToWorld + +Convert a given point from screen into world space +=============== +*/ +void R_ScreenToWorld( const vec3_t screen, vec3_t point ) +{ + matrix4x4 screenToWorld; + float w; + + if( !point || !screen ) + return; + + Matrix4x4_Invert_Full( screenToWorld, RI.worldviewProjectionMatrix ); + + point[0] = screen[0] * screenToWorld[0][0] + screen[1] * screenToWorld[0][1] + screen[2] * screenToWorld[0][2] + screenToWorld[0][3]; + point[1] = screen[0] * screenToWorld[1][0] + screen[1] * screenToWorld[1][1] + screen[2] * screenToWorld[1][2] + screenToWorld[1][3]; + point[2] = screen[0] * screenToWorld[2][0] + screen[1] * screenToWorld[2][1] + screen[2] * screenToWorld[2][2] + screenToWorld[2][3]; + w = screen[0] * screenToWorld[3][0] + screen[1] * screenToWorld[3][1] + screen[2] * screenToWorld[3][2] + screenToWorld[3][3]; + if( w != 0.0f ) VectorScale( point, ( 1.0f / w ), point ); +} + +#endif + +/* +=============== +R_PushScene +=============== +*/ +void R_PushScene( void ) +{ + if( ++tr.draw_stack_pos >= MAX_DRAW_STACK ) + gEngfuncs.Host_Error( "draw stack overflow\n" ); + + tr.draw_list = &tr.draw_stack[tr.draw_stack_pos]; +} + +/* +=============== +R_PopScene +=============== +*/ +void R_PopScene( void ) +{ + if( --tr.draw_stack_pos < 0 ) + gEngfuncs.Host_Error( "draw stack underflow\n" ); + tr.draw_list = &tr.draw_stack[tr.draw_stack_pos]; +} + +/* +=============== +R_ClearScene +=============== +*/ +void R_ClearScene( void ) +{ + tr.draw_list->num_solid_entities = 0; + tr.draw_list->num_trans_entities = 0; + tr.draw_list->num_beam_entities = 0; + + // clear the scene befor start new frame + if( gEngfuncs.drawFuncs->R_ClearScene != NULL ) + gEngfuncs.drawFuncs->R_ClearScene(); + +} + +/* +=============== +R_AddEntity +=============== +*/ +qboolean R_AddEntity( struct cl_entity_s *clent, int type ) +{ + if( !r_drawentities->value ) + return false; // not allow to drawing + + if( !clent || !clent->model ) + return false; // if set to invisible, skip + + if( FBitSet( clent->curstate.effects, EF_NODRAW )) + return false; // done + + if( !R_ModelOpaque( clent->curstate.rendermode ) && gEngfuncs.CL_FxBlend( clent ) <= 0 ) + return true; // invisible + + if( type == ET_FRAGMENTED ) + r_stats.c_client_ents++; + + if( R_OpaqueEntity( clent )) + { + // opaque + if( tr.draw_list->num_solid_entities >= MAX_VISIBLE_PACKET ) + return false; + + tr.draw_list->solid_entities[tr.draw_list->num_solid_entities] = clent; + tr.draw_list->num_solid_entities++; + } + else + { + // translucent + if( tr.draw_list->num_trans_entities >= MAX_VISIBLE_PACKET ) + return false; + + tr.draw_list->trans_entities[tr.draw_list->num_trans_entities] = clent; + tr.draw_list->num_trans_entities++; + } + + return true; +} + +/* +============= +R_Clear +============= +*/ +static void R_Clear( int bitMask ) +{ + int bits; +#if 0 + if( gEngfuncs.CL_IsDevOverviewMode( )) + pglClearColor( 0.0f, 1.0f, 0.0f, 1.0f ); // green background (Valve rules) + else pglClearColor( 0.5f, 0.5f, 0.5f, 1.0f ); + + bits = GL_DEPTH_BUFFER_BIT; + + if( glState.stencilEnabled ) + bits |= GL_STENCIL_BUFFER_BIT; + + bits &= bitMask; + + pglClear( bits ); + + // change ordering for overview + if( RI.drawOrtho ) + { + gldepthmin = 1.0f; + gldepthmax = 0.0f; + } + else + { + gldepthmin = 0.0f; + gldepthmax = 1.0f; + } + + pglDepthFunc( GL_LEQUAL ); + pglDepthRange( gldepthmin, gldepthmax ); +#endif + memset( vid.buffer, 0, 1920*1080*2); +} + +//============================================================================= +/* +=============== +R_GetFarClip +=============== +*/ +static float R_GetFarClip( void ) +{ + if( WORLDMODEL && RI.drawWorld ) + return MOVEVARS->zmax * 1.73f; + return 2048.0f; +} + +/* +=============== +R_SetupFrustum +=============== +*/ +void R_SetupFrustum( void ) +{ +#if 0 + ref_overview_t *ov = gEngfuncs.GetOverviewParms(); + + if( RP_NORMALPASS() && ( gEngfuncs.GetWaterLevel() >= 3 )) + { + RI.fov_x = atan( tan( DEG2RAD( RI.fov_x ) / 2 ) * ( 0.97 + sin( gpGlobals->time * 1.5 ) * 0.03 )) * 2 / (M_PI / 180.0); + RI.fov_y = atan( tan( DEG2RAD( RI.fov_y ) / 2 ) * ( 1.03 - sin( gpGlobals->time * 1.5 ) * 0.03 )) * 2 / (M_PI / 180.0); + } + + // build the transformation matrix for the given view angles + AngleVectors( RI.viewangles, RI.vforward, RI.vright, RI.vup ); + + if( !r_lockfrustum->value ) + { + VectorCopy( RI.vieworg, RI.cullorigin ); + VectorCopy( RI.vforward, RI.cull_vforward ); + VectorCopy( RI.vright, RI.cull_vright ); + VectorCopy( RI.vup, RI.cull_vup ); + } + + if( RI.drawOrtho ) + GL_FrustumInitOrtho( &RI.frustum, ov->xLeft, ov->xRight, ov->yTop, ov->yBottom, ov->zNear, ov->zFar ); + else GL_FrustumInitProj( &RI.frustum, 0.0f, R_GetFarClip(), RI.fov_x, RI.fov_y ); // NOTE: we ignore nearplane here (mirrors only) +#endif +} + +/* +============= +R_SetupProjectionMatrix +============= +*/ +static void R_SetupProjectionMatrix( matrix4x4 m ) +{ +#if 0 + GLdouble xMin, xMax, yMin, yMax, zNear, zFar; + + if( RI.drawOrtho ) + { + ref_overview_t *ov = gEngfuncs.GetOverviewParms(); + Matrix4x4_CreateOrtho( m, ov->xLeft, ov->xRight, ov->yTop, ov->yBottom, ov->zNear, ov->zFar ); + return; + } + + RI.farClip = R_GetFarClip(); + + zNear = 4.0f; + zFar = max( 256.0f, RI.farClip ); + + yMax = zNear * tan( RI.fov_y * M_PI / 360.0 ); + yMin = -yMax; + + xMax = zNear * tan( RI.fov_x * M_PI / 360.0 ); + xMin = -xMax; + + Matrix4x4_CreateProjection( m, xMax, xMin, yMax, yMin, zNear, zFar ); +#endif +} + +/* +============= +R_SetupModelviewMatrix +============= +*/ +static void R_SetupModelviewMatrix( matrix4x4 m ) +{ +#if 0 + Matrix4x4_CreateModelview( m ); + Matrix4x4_ConcatRotate( m, -RI.viewangles[2], 1, 0, 0 ); + Matrix4x4_ConcatRotate( m, -RI.viewangles[0], 0, 1, 0 ); + Matrix4x4_ConcatRotate( m, -RI.viewangles[1], 0, 0, 1 ); + Matrix4x4_ConcatTranslate( m, -RI.vieworg[0], -RI.vieworg[1], -RI.vieworg[2] ); +#endif +} + +/* +============= +R_LoadIdentity +============= +*/ +void R_LoadIdentity( void ) +{ +#if 0 + if( tr.modelviewIdentity ) return; + + Matrix4x4_LoadIdentity( RI.objectMatrix ); + Matrix4x4_Copy( RI.modelviewMatrix, RI.worldviewMatrix ); + + pglMatrixMode( GL_MODELVIEW ); + GL_LoadMatrix( RI.modelviewMatrix ); + tr.modelviewIdentity = true; +#endif +} + +/* +============= +R_RotateForEntity +============= +*/ +void R_RotateForEntity( cl_entity_t *e ) +{ +#if 0 + float scale = 1.0f; + + if( e == gEngfuncs.GetEntityByIndex( 0 ) ) + { + R_LoadIdentity(); + return; + } + + if( e->model->type != mod_brush && e->curstate.scale > 0.0f ) + scale = e->curstate.scale; + + Matrix4x4_CreateFromEntity( RI.objectMatrix, e->angles, e->origin, scale ); + Matrix4x4_ConcatTransforms( RI.modelviewMatrix, RI.worldviewMatrix, RI.objectMatrix ); + + pglMatrixMode( GL_MODELVIEW ); + GL_LoadMatrix( RI.modelviewMatrix ); + tr.modelviewIdentity = false; +#endif +} + +/* +============= +R_TranslateForEntity +============= +*/ +void R_TranslateForEntity( cl_entity_t *e ) +{ +#if 0 + float scale = 1.0f; + + if( e == gEngfuncs.GetEntityByIndex( 0 ) ) + { + R_LoadIdentity(); + return; + } + + if( e->model->type != mod_brush && e->curstate.scale > 0.0f ) + scale = e->curstate.scale; + + Matrix4x4_CreateFromEntity( RI.objectMatrix, vec3_origin, e->origin, scale ); + Matrix4x4_ConcatTransforms( RI.modelviewMatrix, RI.worldviewMatrix, RI.objectMatrix ); + + pglMatrixMode( GL_MODELVIEW ); + GL_LoadMatrix( RI.modelviewMatrix ); + tr.modelviewIdentity = false; +#endif +} + +/* +=============== +R_FindViewLeaf +=============== +*/ +void R_FindViewLeaf( void ) +{ + RI.oldviewleaf = RI.viewleaf; + RI.viewleaf = gEngfuncs.Mod_PointInLeaf( RI.pvsorigin, WORLDMODEL->nodes ); +} + +/* +=============== +R_SetupFrame +=============== +*/ +static void R_SetupFrame( void ) +{ + // setup viewplane dist + RI.viewplanedist = DotProduct( RI.vieworg, RI.vforward ); + +// if( !gl_nosort->value ) + { + // sort translucents entities by rendermode and distance + qsort( tr.draw_list->trans_entities, tr.draw_list->num_trans_entities, sizeof( cl_entity_t* ), R_TransEntityCompare ); + } + + // current viewleaf + if( RI.drawWorld ) + { + RI.isSkyVisible = false; // unknown at this moment + R_FindViewLeaf(); + } + + // setup twice until globals fully refactored + R_SetupFrameQ(); +} +#if 0 + +/* +============= +R_SetupGL +============= +*/ +void R_SetupGL( qboolean set_gl_state ) +{ + R_SetupModelviewMatrix( RI.worldviewMatrix ); + R_SetupProjectionMatrix( RI.projectionMatrix ); + + Matrix4x4_Concat( RI.worldviewProjectionMatrix, RI.projectionMatrix, RI.worldviewMatrix ); + + if( !set_gl_state ) return; + + if( RP_NORMALPASS( )) + { + int x, x2, y, y2; + + // set up viewport (main, playersetup) + x = floor( RI.viewport[0] * gpGlobals->width / gpGlobals->width ); + x2 = ceil(( RI.viewport[0] + RI.viewport[2] ) * gpGlobals->width / gpGlobals->width ); + y = floor( gpGlobals->height - RI.viewport[1] * gpGlobals->height / gpGlobals->height ); + y2 = ceil( gpGlobals->height - ( RI.viewport[1] + RI.viewport[3] ) * gpGlobals->height / gpGlobals->height ); + + pglViewport( x, y2, x2 - x, y - y2 ); + } + else + { + // envpass, mirrorpass + pglViewport( RI.viewport[0], RI.viewport[1], RI.viewport[2], RI.viewport[3] ); + } + + pglMatrixMode( GL_PROJECTION ); + GL_LoadMatrix( RI.projectionMatrix ); + + pglMatrixMode( GL_MODELVIEW ); + GL_LoadMatrix( RI.worldviewMatrix ); + + if( FBitSet( RI.params, RP_CLIPPLANE )) + { + GLdouble clip[4]; + mplane_t *p = &RI.clipPlane; + + clip[0] = p->normal[0]; + clip[1] = p->normal[1]; + clip[2] = p->normal[2]; + clip[3] = -p->dist; + + pglClipPlane( GL_CLIP_PLANE0, clip ); + pglEnable( GL_CLIP_PLANE0 ); + } + + GL_Cull( GL_FRONT ); + + pglDisable( GL_BLEND ); + pglDisable( GL_ALPHA_TEST ); + pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); +} + +/* +============= +R_EndGL +============= +*/ +static void R_EndGL( void ) +{ + if( RI.params & RP_CLIPPLANE ) + pglDisable( GL_CLIP_PLANE0 ); +} + +#endif + +/* +============= +R_RecursiveFindWaterTexture + +using to find source waterleaf with +watertexture to grab fog values from it +============= +*/ +static image_t *R_RecursiveFindWaterTexture( const mnode_t *node, const mnode_t *ignore, qboolean down ) +{ + image_t *tex = NULL; + + // assure the initial node is not null + // we could check it here, but we would rather check it + // outside the call to get rid of one additional recursion level + Assert( node != NULL ); + + // ignore solid nodes + if( node->contents == CONTENTS_SOLID ) + return NULL; + + if( node->contents < 0 ) + { + mleaf_t *pleaf; + msurface_t **mark; + int i, c; + + // ignore non-liquid leaves + if( node->contents != CONTENTS_WATER && node->contents != CONTENTS_LAVA && node->contents != CONTENTS_SLIME ) + return NULL; + + // find texture + pleaf = (mleaf_t *)node; + mark = pleaf->firstmarksurface; + c = pleaf->nummarksurfaces; + + for( i = 0; i < c; i++, mark++ ) + { + if( (*mark)->flags & SURF_DRAWTURB && (*mark)->texinfo && (*mark)->texinfo->texture ) + return R_GetTexture( (*mark)->texinfo->texture->gl_texturenum ); + } + + // texture not found + return NULL; + } + + // this is a regular node + // traverse children + if( node->children[0] && ( node->children[0] != ignore )) + { + tex = R_RecursiveFindWaterTexture( node->children[0], node, true ); + if( tex ) return tex; + } + + if( node->children[1] && ( node->children[1] != ignore )) + { + tex = R_RecursiveFindWaterTexture( node->children[1], node, true ); + if( tex ) return tex; + } + + // for down recursion, return immediately + if( down ) return NULL; + + // texture not found, step up if any + if( node->parent ) + return R_RecursiveFindWaterTexture( node->parent, node, false ); + + // top-level node, bail out + return NULL; +} + +/* +============= +R_CheckFog + +check for underwater fog +Using backward recursion to find waterline leaf +from underwater leaf (idea: XaeroX) +============= +*/ +static void R_CheckFog( void ) +{ + cl_entity_t *ent; + image_t *tex; + int i, cnt, count; + + // quake global fog + if( gEngfuncs.Host_IsQuakeCompatible( )) + { + if( !MOVEVARS->fog_settings ) + { + // if( pglIsEnabled( GL_FOG )) + // pglDisable( GL_FOG ); + RI.fogEnabled = false; + return; + } + + // quake-style global fog + RI.fogColor[0] = ((MOVEVARS->fog_settings & 0xFF000000) >> 24) / 255.0f; + RI.fogColor[1] = ((MOVEVARS->fog_settings & 0xFF0000) >> 16) / 255.0f; + RI.fogColor[2] = ((MOVEVARS->fog_settings & 0xFF00) >> 8) / 255.0f; + RI.fogDensity = ((MOVEVARS->fog_settings & 0xFF) / 255.0f) * 0.01f; + RI.fogStart = RI.fogEnd = 0.0f; + RI.fogColor[3] = 1.0f; + RI.fogCustom = false; + RI.fogEnabled = true; + RI.fogSkybox = true; + return; + } + + RI.fogEnabled = false; + + if( RI.onlyClientDraw || gEngfuncs.GetWaterLevel() < 3 || !RI.drawWorld || !RI.viewleaf ) + { + if( RI.cached_waterlevel == 3 ) + { + // in some cases waterlevel jumps from 3 to 1. Catch it + RI.cached_waterlevel = gEngfuncs.GetWaterLevel(); + RI.cached_contents = CONTENTS_EMPTY; + //if( !RI.fogCustom ) pglDisable( GL_FOG ); + } + return; + } + + ent = gEngfuncs.CL_GetWaterEntity( RI.vieworg ); + if( ent && ent->model && ent->model->type == mod_brush && ent->curstate.skin < 0 ) + cnt = ent->curstate.skin; + else cnt = RI.viewleaf->contents; + + RI.cached_waterlevel = gEngfuncs.GetWaterLevel(); + + if( !IsLiquidContents( RI.cached_contents ) && IsLiquidContents( cnt )) + { + tex = NULL; + + // check for water texture + if( ent && ent->model && ent->model->type == mod_brush ) + { + msurface_t *surf; + + count = ent->model->nummodelsurfaces; + + for( i = 0, surf = &ent->model->surfaces[ent->model->firstmodelsurface]; i < count; i++, surf++ ) + { + if( surf->flags & SURF_DRAWTURB && surf->texinfo && surf->texinfo->texture ) + { + tex = R_GetTexture( surf->texinfo->texture->gl_texturenum ); + RI.cached_contents = ent->curstate.skin; + break; + } + } + } + else + { + tex = R_RecursiveFindWaterTexture( RI.viewleaf->parent, NULL, false ); + if( tex ) RI.cached_contents = RI.viewleaf->contents; + } + + if( !tex ) return; // no valid fogs + + // copy fog params + RI.fogColor[0] = tex->fogParams[0] / 255.0f; + RI.fogColor[1] = tex->fogParams[1] / 255.0f; + RI.fogColor[2] = tex->fogParams[2] / 255.0f; + RI.fogDensity = tex->fogParams[3] * 0.000025f; + RI.fogStart = RI.fogEnd = 0.0f; + RI.fogColor[3] = 1.0f; + RI.fogCustom = false; + RI.fogEnabled = true; + RI.fogSkybox = true; + } + else + { + RI.fogCustom = false; + RI.fogEnabled = true; + RI.fogSkybox = true; + } +} + +/* +============= +R_CheckGLFog + +special condition for Spirit 1.9 +that used direct calls of glFog-functions +============= +*/ +static void R_CheckGLFog( void ) +{ +#ifdef HACKS_RELATED_HLMODS + if(( !RI.fogEnabled && !RI.fogCustom ) && pglIsEnabled( GL_FOG ) && VectorIsNull( RI.fogColor )) + { + // fill the fog color from GL-state machine + pglGetFloatv( GL_FOG_COLOR, RI.fogColor ); + RI.fogSkybox = true; + } +#endif +} + +/* +============= +R_DrawFog + +============= +*/ +void R_DrawFog( void ) +{ + if( !RI.fogEnabled ) return; +#if 0 + pglEnable( GL_FOG ); + if( gEngfuncs.Host_IsQuakeCompatible( )) + pglFogi( GL_FOG_MODE, GL_EXP2 ); + else pglFogi( GL_FOG_MODE, GL_EXP ); + pglFogf( GL_FOG_DENSITY, RI.fogDensity ); + pglFogfv( GL_FOG_COLOR, RI.fogColor ); + pglHint( GL_FOG_HINT, GL_NICEST ); +#endif +} + +/* +============= +R_DrawEntitiesOnList +============= +*/ +void R_DrawEntitiesOnList( void ) +{ + int i; + + tr.blend = 1.0f; +// GL_CheckForErrors(); + + // first draw solid entities + for( i = 0; i < tr.draw_list->num_solid_entities && !RI.onlyClientDraw; i++ ) + { + RI.currententity = tr.draw_list->solid_entities[i]; + RI.currentmodel = RI.currententity->model; + + Assert( RI.currententity != NULL ); + Assert( RI.currentmodel != NULL ); + + switch( RI.currentmodel->type ) + { + case mod_brush: + //R_DrawBrushModel( RI.currententity ); + break; + case mod_alias: + //R_DrawAliasModel( RI.currententity ); + break; + case mod_studio: + //R_DrawStudioModel( RI.currententity ); + break; + default: + break; + } + } + +// GL_CheckForErrors(); + + // quake-specific feature +// R_DrawAlphaTextureChains(); + +// GL_CheckForErrors(); + + // draw sprites seperately, because of alpha blending + for( i = 0; i < tr.draw_list->num_solid_entities && !RI.onlyClientDraw; i++ ) + { + RI.currententity = tr.draw_list->solid_entities[i]; + RI.currentmodel = RI.currententity->model; + + Assert( RI.currententity != NULL ); + Assert( RI.currentmodel != NULL ); + + switch( RI.currentmodel->type ) + { + case mod_sprite: + // R_DrawSpriteModel( RI.currententity ); + break; + } + } + +// GL_CheckForErrors(); + + if( !RI.onlyClientDraw ) + { + gEngfuncs.CL_DrawEFX( tr.frametime, false ); + } + +// GL_CheckForErrors(); + + if( RI.drawWorld ) + gEngfuncs.pfnDrawNormalTriangles(); + +// GL_CheckForErrors(); + + // then draw translucent entities + for( i = 0; i < tr.draw_list->num_trans_entities && !RI.onlyClientDraw; i++ ) + { + RI.currententity = tr.draw_list->trans_entities[i]; + RI.currentmodel = RI.currententity->model; + + // handle studiomodels with custom rendermodes on texture + if( RI.currententity->curstate.rendermode != kRenderNormal ) + tr.blend = gEngfuncs.CL_FxBlend( RI.currententity ) / 255.0f; + else tr.blend = 1.0f; // draw as solid but sorted by distance + + if( tr.blend <= 0.0f ) continue; + + Assert( RI.currententity != NULL ); + Assert( RI.currentmodel != NULL ); + + switch( RI.currentmodel->type ) + { + case mod_brush: + // R_DrawBrushModel( RI.currententity ); + break; + case mod_alias: + //R_DrawAliasModel( RI.currententity ); + break; + case mod_studio: + // R_DrawStudioModel( RI.currententity ); + break; + case mod_sprite: + // R_DrawSpriteModel( RI.currententity ); + break; + default: + break; + } + } + +// GL_CheckForErrors(); + + if( RI.drawWorld ) + { + // pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + gEngfuncs.pfnDrawTransparentTriangles (); + } + +// GL_CheckForErrors(); + + if( !RI.onlyClientDraw ) + { + R_AllowFog( false ); + gEngfuncs.CL_DrawEFX( tr.frametime, true ); + R_AllowFog( true ); + } + + //GL_CheckForErrors(); + +// pglDisable( GL_BLEND ); // Trinity Render issues + + //if( !RI.onlyClientDraw ) + //R_DrawViewModel(); + gEngfuncs.CL_ExtraUpdate(); + + //GL_CheckForErrors(); +} + +#if 0 + +/* +============= +R_DrawBEntitiesOnList +============= +*/ +void R_DrawBEntitiesOnList (void) +{ + int i, clipflags; + vec3_t oldorigin; + vec3_t mins, maxs; + float minmaxs[6]; + mnode_t *topnode; + + if (!r_drawentities->value) + return; + + VectorCopy (modelorg, oldorigin); + insubmodel = true; + r_dlightframecount = r_framecount; + + for (i=0 ; imodel; + if (!currentmodel) + continue; + if (currentmodel->nummodelsurfaces == 0) + continue; // clip brush only + if ( currententity->flags & RF_BEAM ) + continue; + if (currentmodel->type != mod_brush) + continue; + // see if the bounding box lets us trivially reject, also sets + // trivial accept status + RotatedBBox (currentmodel->mins, currentmodel->maxs, + currententity->angles, mins, maxs); + VectorAdd (mins, currententity->origin, minmaxs); + VectorAdd (maxs, currententity->origin, (minmaxs+3)); + + clipflags = R_BmodelCheckBBox (minmaxs); + if (clipflags == BMODEL_FULLY_CLIPPED) + continue; // off the edge of the screen + + topnode = R_FindTopnode (minmaxs, minmaxs+3); + if (!topnode) + continue; // no part in a visible leaf + + VectorCopy (currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + + r_pcurrentvertbase = currentmodel->vertexes; + + // FIXME: stop transforming twice + R_RotateBmodel (); + + // calculate dynamic lighting for bmodel + R_PushDlights (currentmodel); + + if (topnode->contents == CONTENTS_NODE) + { + // not a leaf; has to be clipped to the world BSP + r_clipflags = clipflags; + R_DrawSolidClippedSubmodelPolygons (currentmodel, topnode); + } + else + { + // falls entirely in one leaf, so we just put all the + // edges in the edge list and let 1/z sorting handle + // drawing order + R_DrawSubmodelPolygons (currentmodel, clipflags, topnode); + } + + // put back world rotation and frustum clipping + // FIXME: R_RotateBmodel should just work off base_vxx + VectorCopy (base_vpn, vpn); + VectorCopy (base_vup, vup); + VectorCopy (base_vright, vright); + VectorCopy (oldorigin, modelorg); + R_TransformFrustum (); + } + + insubmodel = false; +} +#endif + +/* +================ +R_EdgeDrawing +================ +*/ +void R_EdgeDrawing (void) +{ + edge_t ledges[NUMSTACKEDGES + + ((CACHE_SIZE - 1) / sizeof(edge_t)) + 1]; + surf_t lsurfs[NUMSTACKSURFACES + + ((CACHE_SIZE - 1) / sizeof(surf_t)) + 1]; + + if ( !RI.drawWorld ) + return; + + if (auxedges) + { + r_edges = auxedges; + } + else + { + r_edges = (edge_t *) + (((long)&ledges[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); + } + + if (r_surfsonstack) + { + surfaces = (surf_t *) + (((long)&lsurfs[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); + surf_max = &surfaces[r_cnumsurfs]; + // surface 0 doesn't really exist; it's just a dummy because index 0 + // is used to indicate no edge attached to surface + surfaces--; + R_SurfacePatch (); + } + + R_BeginEdgeFrame (); + + // this will prepare edges + R_RenderWorld (); + + // move brushes to separate list to merge with edges? + //R_DrawBEntitiesOnList (); + + // display all edges + R_ScanEdges (); +} + +/* +================ +R_RenderScene + +R_SetupRefParams must be called right before +================ +*/ +void R_RenderScene( void ) +{ + if( !WORLDMODEL && RI.drawWorld ) + gEngfuncs.Host_Error( "R_RenderView: NULL worldmodel\n" ); + + // frametime is valid only for normal pass + if( RP_NORMALPASS( )) + tr.frametime = gpGlobals->time - gpGlobals->oldtime; + else tr.frametime = 0.0; + + // begin a new frame + tr.framecount++; + +// R_PushDlights(); + + R_SetupFrustum(); + R_SetupFrame(); +// R_SetupGL( true ); + R_Clear( ~0 ); + + //R_MarkLeaves(); + R_DrawFog (); + // R_PushDlights (r_worldmodel); ?? + R_CheckGLFog(); + //R_DrawWorld(); + R_EdgeDrawing (); + R_CheckFog(); + + gEngfuncs.CL_ExtraUpdate (); // don't let sound get messed up if going slow + + R_DrawEntitiesOnList(); + +// R_DrawWaterSurfaces(); + +// R_EndGL(); +} + +/* +=============== +R_DoResetGamma + +gamma will be reset for +some type of screenshots +=============== +*/ +qboolean R_DoResetGamma( void ) +{ + // FIXME: this looks ugly. apply the backward gamma changes to the output image + return false; +#if 0 + switch( cls.scrshot_action ) + { + case scrshot_normal: + if( CL_IsDevOverviewMode( )) + return true; + return false; + case scrshot_snapshot: + if( CL_IsDevOverviewMode( )) + return true; + return false; + case scrshot_plaque: + case scrshot_savegame: + case scrshot_envshot: + case scrshot_skyshot: + case scrshot_mapshot: + return true; + default: + return false; + } +#endif +} + +/* +=============== +R_BeginFrame +=============== +*/ +void R_BeginFrame( qboolean clearScene ) +{ + + if( R_DoResetGamma( )) + { + gEngfuncs.BuildGammaTable( 1.8f, 0.0f ); + // glConfig.softwareGammaUpdate = true; + // GL_RebuildLightmaps(); + // glConfig.softwareGammaUpdate = false; + + // next frame will be restored gamma + // SetBits( vid_brightness->flags, FCVAR_CHANGED ); + // SetBits( vid_gamma->flags, FCVAR_CHANGED ); + } + else if( FBitSet( vid_gamma->flags, FCVAR_CHANGED ) || FBitSet( vid_brightness->flags, FCVAR_CHANGED )) + { + // gEngfuncs.BuildGammaTable( vid_gamma->value, vid_brightness->value ); + //glConfig.softwareGammaUpdate = true; + // GL_RebuildLightmaps(); + //glConfig.softwareGammaUpdate = false; + } + + R_Set2DMode( true ); + + // draw buffer stuff + //pglDrawBuffer( GL_BACK ); + + // update texture parameters + //if( FBitSet( gl_texture_nearest->flags|gl_lightmap_nearest->flags|gl_texture_anisotropy->flags|gl_texture_lodbias->flags, FCVAR_CHANGED )) + //R_SetTextureParameters(); + + gEngfuncs.CL_ExtraUpdate (); +} + +/* +=============== +R_SetupRefParams + +set initial params for renderer +=============== +*/ +void R_SetupRefParams( const ref_viewpass_t *rvp ) +{ + RI.params = RP_NONE; + RI.drawWorld = FBitSet( rvp->flags, RF_DRAW_WORLD ); + RI.onlyClientDraw = FBitSet( rvp->flags, RF_ONLY_CLIENTDRAW ); + RI.farClip = 0; + + if( !FBitSet( rvp->flags, RF_DRAW_CUBEMAP )) + RI.drawOrtho = FBitSet( rvp->flags, RF_DRAW_OVERVIEW ); + else RI.drawOrtho = false; + + // setup viewport + RI.viewport[0] = rvp->viewport[0]; + RI.viewport[1] = rvp->viewport[1]; + RI.viewport[2] = rvp->viewport[2]; + RI.viewport[3] = rvp->viewport[3]; + + // calc FOV + RI.fov_x = rvp->fov_x; + RI.fov_y = rvp->fov_y; + + VectorCopy( rvp->vieworigin, RI.vieworg ); + VectorCopy( rvp->viewangles, RI.viewangles ); + VectorCopy( rvp->vieworigin, RI.pvsorigin ); +} + +/* +=============== +R_RenderFrame +=============== +*/ +int R_RenderFrame( const ref_viewpass_t *rvp ) +{ + if( r_norefresh->value ) + return 1; + + // setup the initial render params + R_SetupRefParams( rvp ); + + // completely override rendering + if( gEngfuncs.drawFuncs->GL_RenderFrame != NULL ) + { + tr.fCustomRendering = true; + + if( gEngfuncs.drawFuncs->GL_RenderFrame( rvp )) + { + //R_GatherPlayerLight(); + tr.realframecount++; + tr.fResetVis = true; + return 1; + } + } + + tr.fCustomRendering = false; +// if( !RI.onlyClientDraw ) + // R_RunViewmodelEvents(); + + tr.realframecount++; // right called after viewmodel events + R_RenderScene(); + + return 1; +} + +/* +=============== +R_EndFrame +=============== +*/ +void R_EndFrame( void ) +{ + // flush any remaining 2D bits + R_Set2DMode( false ); + + // blit pixels with GL until engine supports REF_SOFT context + R_BlitScreen(); +} + +/* +=============== +R_DrawCubemapView +=============== +*/ +void R_DrawCubemapView( const vec3_t origin, const vec3_t angles, int size ) +{ + ref_viewpass_t rvp; + + // basic params + rvp.flags = rvp.viewentity = 0; + SetBits( rvp.flags, RF_DRAW_WORLD ); + SetBits( rvp.flags, RF_DRAW_CUBEMAP ); + + rvp.viewport[0] = rvp.viewport[1] = 0; + rvp.viewport[2] = rvp.viewport[3] = size; + rvp.fov_x = rvp.fov_y = 90.0f; // this is a final fov value + + // setup origin & angles + VectorCopy( origin, rvp.vieworigin ); + VectorCopy( angles, rvp.viewangles ); + + R_RenderFrame( &rvp ); + + RI.viewleaf = NULL; // force markleafs next frame +} + +/* +=============== +R_NewMap +=============== +*/ +void R_NewMap (void) +{ + r_viewcluster = -1; + + r_cnumsurfs = sw_maxsurfs->value; + + if (r_cnumsurfs <= MINSURFACES) + r_cnumsurfs = MINSURFACES; + + if (r_cnumsurfs > NUMSTACKSURFACES) + { + surfaces = malloc (r_cnumsurfs * sizeof(surf_t)); + surface_p = surfaces; + surf_max = &surfaces[r_cnumsurfs]; + r_surfsonstack = false; + // surface 0 doesn't really exist; it's just a dummy because index 0 + // is used to indicate no edge attached to surface + surfaces--; + R_SurfacePatch (); + } + else + { + r_surfsonstack = true; + } + + r_maxedgesseen = 0; + r_maxsurfsseen = 0; + + r_numallocatededges = sw_maxedges->value; + + if (r_numallocatededges < MINEDGES) + r_numallocatededges = MINEDGES; + + if (r_numallocatededges <= NUMSTACKEDGES) + { + auxedges = NULL; + } + else + { + auxedges = malloc (r_numallocatededges * sizeof(edge_t)); + } +} + + + + +qboolean R_Init() +{ + gl_emboss_scale = gEngfuncs.Cvar_Get( "gl_emboss_scale", "0", FCVAR_ARCHIVE|FCVAR_LATCH, "fake bumpmapping scale" ); + vid_gamma = gEngfuncs.pfnGetCvarPointer( "gamma", 0 ); + r_norefresh = gEngfuncs.Cvar_Get( "r_norefresh", "0", 0, "disable 3D rendering (use with caution)" ); + r_drawentities = gEngfuncs.Cvar_Get( "r_drawentities", "1", FCVAR_CHEAT, "render entities" ); + vid_brightness = gEngfuncs.pfnGetCvarPointer( "brightness", 0 ); + r_fullbright = gEngfuncs.Cvar_Get( "r_fullbright", "0", FCVAR_CHEAT, "disable lightmaps, get fullbright for entities" ); + sw_mipcap = gEngfuncs.Cvar_Get( "r_fullbright", "0", FCVAR_CHEAT, "disable lightmaps, get fullbright for entities" ); + +// sw_aliasstats = ri.Cvar_Get ("sw_polymodelstats", "0", 0); +// sw_allow_modex = ri.Cvar_Get( "sw_allow_modex", "1", CVAR_ARCHIVE ); + sw_clearcolor = gEngfuncs.Cvar_Get ("sw_clearcolor", "2", 0, "screen clear color"); + sw_drawflat = gEngfuncs.Cvar_Get ("sw_drawflat", "0", 0, ""); + sw_draworder = gEngfuncs.Cvar_Get ("sw_draworder", "0", 0, ""); + sw_maxedges = gEngfuncs.Cvar_Get ("sw_maxedges", "32", 0, ""); + sw_maxsurfs = gEngfuncs.Cvar_Get ("sw_maxsurfs", "0", 0, ""); + sw_mipscale = gEngfuncs.Cvar_Get ("sw_mipscale", "1", 0, ""); + sw_reportedgeout = gEngfuncs.Cvar_Get ("sw_reportedgeout", "0", 0, ""); + sw_reportsurfout = gEngfuncs.Cvar_Get ("sw_reportsurfout", "0", 0, ""); + sw_stipplealpha = gEngfuncs.Cvar_Get( "sw_stipplealpha", "0", FCVAR_ARCHIVE, "" ); + sw_surfcacheoverride = gEngfuncs.Cvar_Get ("sw_surfcacheoverride", "0", 0, ""); + sw_waterwarp = gEngfuncs.Cvar_Get ("sw_waterwarp", "1", 0, ""); + sw_mode = gEngfuncs.Cvar_Get( "sw_mode", "0", FCVAR_ARCHIVE, ""); + + //r_lefthand = ri.Cvar_Get( "hand", "0", FCVAR_USERINFO | FCVAR_ARCHIVE ); +// r_speeds = ri.Cvar_Get ("r_speeds", "0", 0); + + //r_drawworld = ri.Cvar_Get ("r_drawworld", "1", 0); + //r_dspeeds = ri.Cvar_Get ("r_dspeeds", "0", 0); +// r_lightlevel = ri.Cvar_Get ("r_lightlevel", "0", 0); + //r_lerpmodels = ri.Cvar_Get( "r_lerpmodels", "1", 0 ); + //r_novis = ri.Cvar_Get( "r_novis", "0", 0 ); + + // create the window and set up the context + r_temppool = Mem_AllocPool( "ref_sw zone" ); + + vid.width = 1920; + vid.height = 1080; + vid.rowbytes = 1920; // rowpixels + + vid.buffer = Mem_Malloc( r_temppool, 1920*1080*sizeof( pixel_t ) ); + if( !gEngfuncs.R_Init_Video( REF_GL )) // request GL context + { + gEngfuncs.R_Free_Video(); + + gEngfuncs.Host_Error( "Can't initialize video subsystem\nProbably driver was not installed" ); + return false; + } + + + R_InitImages(); + // init draw stack + tr.draw_list = &tr.draw_stack[0]; + tr.draw_stack_pos = 0; + return true; +} + +void R_Shutdown() +{ + R_ShutdownImages(); + gEngfuncs.R_Free_Video(); +} + diff --git a/r_misc.c b/r_misc.c new file mode 100644 index 00000000..6ba955ac --- /dev/null +++ b/r_misc.c @@ -0,0 +1,421 @@ +/* +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. + +*/ +// r_misc.c + +#include "r_local.h" + +#define NUM_MIPS 4 + +cvar_t *sw_mipcap; +cvar_t *sw_mipscale; + +surfcache_t *d_initial_rover; +qboolean d_roverwrapped; +int d_minmip; +float d_scalemip[NUM_MIPS-1]; + +static float basemip[NUM_MIPS-1] = {1.0, 0.5*0.8, 0.25*0.8}; + +extern int d_aflatcolor; + +int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle; + +int d_pix_min, d_pix_max, d_pix_shift; + +int d_scantable[MAXHEIGHT]; +short *zspantable[MAXHEIGHT]; + +/* +================ +D_Patch +================ +*/ +void D_Patch (void) +{ +#if id386 + extern void D_Aff8Patch( void ); + static qboolean protectset8 = false; + extern void D_PolysetAff8Start( void ); + + if (!protectset8) + { + Sys_MakeCodeWriteable ((int)D_PolysetAff8Start, + (int)D_Aff8Patch - (int)D_PolysetAff8Start); + Sys_MakeCodeWriteable ((long)R_Surf8Start, + (long)R_Surf8End - (long)R_Surf8Start); + protectset8 = true; + } + colormap = vid.colormap; + + R_Surf8Patch (); + D_Aff8Patch(); +#endif +} +/* +================ +D_ViewChanged +================ +*/ +unsigned char *alias_colormap; + +void D_ViewChanged (void) +{ + int i; + + scale_for_mip = xscale; + if (yscale > xscale) + scale_for_mip = yscale; + + d_zrowbytes = vid.width * 2; + d_zwidth = vid.width; + + d_pix_min = gpGlobals->width / 320; + if (d_pix_min < 1) + d_pix_min = 1; + + d_pix_max = (int)((float)gpGlobals->height / (320.0 / 4.0) + 0.5); + d_pix_shift = 8 - (int)((float)gpGlobals->height / 320.0 + 0.5); + if (d_pix_max < 1) + d_pix_max = 1; + + d_vrectx = 0;//r_refdef.vrect.x; + d_vrecty = 0;//r_refdef.vrect.y; + d_vrectright_particle = gpGlobals->width - d_pix_max; + d_vrectbottom_particle = + gpGlobals->height - d_pix_max; + + for (i=0 ; iwidth, gpGlobals->height,( int ) sw_clearcolor->value & 0xff ); + } + + alias_colormap = vid.colormap; + + D_Patch (); +} + + + +/* +=================== +R_TransformFrustum +=================== +*/ +void R_TransformFrustum (void) +{ + int i; + vec3_t v, v2; + + for (i=0 ; i<4 ; i++) + { + v[0] = screenedge[i].normal[2]; + v[1] = -screenedge[i].normal[0]; + v[2] = screenedge[i].normal[1]; + + v2[0] = v[1]*vright[0] + v[2]*vup[0] + v[0]*vpn[0]; + v2[1] = v[1]*vright[1] + v[2]*vup[1] + v[0]*vpn[1]; + v2[2] = v[1]*vright[2] + v[2]*vup[2] + v[0]*vpn[2]; + + VectorCopy (v2, view_clipplanes[i].normal); + + view_clipplanes[i].dist = DotProduct (modelorg, v2); + } +} + + +/* +================ +TransformVector +================ +*/ +void TransformVector (vec3_t in, vec3_t out) +{ + out[0] = DotProduct(in,vright); + out[1] = DotProduct(in,vup); + out[2] = DotProduct(in,vpn); +} + +/* +================ +R_TransformPlane +================ +*/ +void R_TransformPlane (mplane_t *p, float *normal, float *dist) +{ + float d; + + d = DotProduct (RI.vieworg, p->normal); + *dist = p->dist - d; +// TODO: when we have rotating entities, this will need to use the view matrix + TransformVector (p->normal, normal); +} + + +/* +=============== +R_SetUpFrustumIndexes +=============== +*/ +void R_SetUpFrustumIndexes (void) +{ + int i, j, *pindex; + + pindex = r_frustum_indexes; + + for (i=0 ; i<4 ; i++) + { + for (j=0 ; j<3 ; j++) + { + if (view_clipplanes[i].normal[j] < 0) + { + pindex[j] = j; + pindex[j+3] = j+3; + } + else + { + pindex[j] = j+3; + pindex[j+3] = j; + } + } + + // FIXME: do just once at start + pfrustum_indexes[i] = pindex; + pindex += 6; + } +} + +/* +=============== +R_ViewChanged + +Called every time the vid structure or r_refdef changes. +Guaranteed to be called before the first refresh +=============== +*/ +void R_ViewChanged (vrect_t *vr) +{ + int i; +#if 0 + r_refdef.vrect = *vr; + + r_refdef.horizontalFieldOfView = 2*tan((float)r_newrefdef.fov_x/360*M_PI);; + verticalFieldOfView = 2*tan((float)r_newrefdef.fov_y/360*M_PI); + + r_refdef.fvrectx = (float)r_refdef.vrect.x; + r_refdef.fvrectx_adj = (float)r_refdef.vrect.x - 0.5; + r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x<<20) + (1<<19) - 1; + r_refdef.fvrecty = (float)r_refdef.vrect.y; + r_refdef.fvrecty_adj = (float)r_refdef.vrect.y - 0.5; + r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width; + r_refdef.vrectright_adj_shift20 = (r_refdef.vrectright<<20) + (1<<19) - 1; + r_refdef.fvrectright = (float)r_refdef.vrectright; + r_refdef.fvrectright_adj = (float)r_refdef.vrectright - 0.5; + r_refdef.vrectrightedge = (float)r_refdef.vrectright - 0.99; + r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height; + r_refdef.fvrectbottom = (float)r_refdef.vrectbottom; + r_refdef.fvrectbottom_adj = (float)r_refdef.vrectbottom - 0.5; + + r_refdef.aliasvrect.x = (int)(r_refdef.vrect.x * r_aliasuvscale); + r_refdef.aliasvrect.y = (int)(r_refdef.vrect.y * r_aliasuvscale); + r_refdef.aliasvrect.width = (int)(r_refdef.vrect.width * r_aliasuvscale); + r_refdef.aliasvrect.height = (int)(r_refdef.vrect.height * r_aliasuvscale); + r_refdef.aliasvrectright = r_refdef.aliasvrect.x + + r_refdef.aliasvrect.width; + r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y + + r_refdef.aliasvrect.height; + + xOrigin = r_refdef.xOrigin; + yOrigin = r_refdef.yOrigin; + +// values for perspective projection +// if math were exact, the values would range from 0.5 to to range+0.5 +// hopefully they wll be in the 0.000001 to range+.999999 and truncate +// the polygon rasterization will never render in the first row or column +// but will definately render in the [range] row and column, so adjust the +// buffer origin to get an exact edge to edge fill + xcenter = ((float)r_refdef.vrect.width * XCENTERING) + + r_refdef.vrect.x - 0.5; + aliasxcenter = xcenter * r_aliasuvscale; + ycenter = ((float)r_refdef.vrect.height * YCENTERING) + + r_refdef.vrect.y - 0.5; + aliasycenter = ycenter * r_aliasuvscale; + + xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView; + aliasxscale = xscale * r_aliasuvscale; + xscaleinv = 1.0 / xscale; + + yscale = xscale; + aliasyscale = yscale * r_aliasuvscale; + yscaleinv = 1.0 / yscale; + xscaleshrink = (r_refdef.vrect.width-6)/r_refdef.horizontalFieldOfView; + yscaleshrink = xscaleshrink; + +// left side clip + screenedge[0].normal[0] = -1.0 / (xOrigin*r_refdef.horizontalFieldOfView); + screenedge[0].normal[1] = 0; + screenedge[0].normal[2] = 1; + screenedge[0].type = PLANE_ANYZ; + +// right side clip + screenedge[1].normal[0] = + 1.0 / ((1.0-xOrigin)*r_refdef.horizontalFieldOfView); + screenedge[1].normal[1] = 0; + screenedge[1].normal[2] = 1; + screenedge[1].type = PLANE_ANYZ; + +// top side clip + screenedge[2].normal[0] = 0; + screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView); + screenedge[2].normal[2] = 1; + screenedge[2].type = PLANE_ANYZ; + +// bottom side clip + screenedge[3].normal[0] = 0; + screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView); + screenedge[3].normal[2] = 1; + screenedge[3].type = PLANE_ANYZ; +#endif + for (i=0 ; i<4 ; i++) + VectorNormalize (screenedge[i].normal); + + D_ViewChanged (); +} + + +/* +=============== +R_SetupFrame +=============== +*/ +void R_SetupFrameQ (void) +{ + int i; + vrect_t vrect; + + if (r_fullbright->flags & FCVAR_CHANGED) + { + r_fullbright->flags &= ~FCVAR_CHANGED; + D_FlushCaches (); // so all lighting changes + } + + r_framecount++; + + +// build the transformation matrix for the given view angles + VectorCopy (RI.vieworg, modelorg); + VectorCopy (RI.vieworg, r_origin); + + AngleVectors (RI.viewangles, vpn, vright, vup); + +// current viewleaf + if ( RI.drawWorld ) + { + r_viewleaf = gEngfuncs.Mod_PointInLeaf (r_origin, WORLDMODEL->nodes); + r_viewcluster = r_viewleaf->cluster; + } + +// if (sw_waterwarp->value && (r_newrefdef.rdflags & RDF_UNDERWATER) ) +// r_dowarp = true; +// else + r_dowarp = false; + + if (r_dowarp) + { // warp into off screen buffer + vrect.x = 0; + vrect.y = 0; + //vrect.width = r_newrefdef.width < WARP_WIDTH ? r_newrefdef.width : WARP_WIDTH; + //vrect.height = r_newrefdef.height < WARP_HEIGHT ? r_newrefdef.height : WARP_HEIGHT; + + d_viewbuffer = r_warpbuffer; + r_screenwidth = WARP_WIDTH; + } + else + { + vrect.x = 0;//r_newrefdef.x; + vrect.y = 0;//r_newrefdef.y; + vrect.width = gpGlobals->width; + vrect.height = gpGlobals->height; + + d_viewbuffer = (void *)vid.buffer; + r_screenwidth = vid.rowbytes; + } + + R_ViewChanged (&vrect); + +// start off with just the four screen edge clip planes + R_TransformFrustum (); + R_SetUpFrustumIndexes (); + +// save base values + VectorCopy (vpn, base_vpn); + VectorCopy (vright, base_vright); + VectorCopy (vup, base_vup); + +// clear frame counts +/* c_faceclip = 0; + d_spanpixcount = 0; + r_polycount = 0; + r_drawnpolycount = 0; + r_wholepolycount = 0; + r_amodels_drawn = 0; + r_outofsurfaces = 0; + r_outofedges = 0;*/ + +// d_setup + d_roverwrapped = false; + d_initial_rover = sc_rover; + + d_minmip = sw_mipcap->value; + if (d_minmip > 3) + d_minmip = 3; + else if (d_minmip < 0) + d_minmip = 0; + + for (i=0 ; i<(NUM_MIPS-1) ; i++) + d_scalemip[i] = basemip[i] * sw_mipscale->value; + + //d_aflatcolor = 0; +} + + +#if !id386 + +/* +================ +R_SurfacePatch +================ +*/ +/*void R_SurfacePatch (void) +{ + // we only patch code on Intel +} +*/ +#endif // !id386 diff --git a/r_rast.c b/r_rast.c new file mode 100644 index 00000000..19666843 --- /dev/null +++ b/r_rast.c @@ -0,0 +1,852 @@ +/* +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. + +*/ +// r_rast.c + +#include + +#include "r_local.h" + +#define MAXLEFTCLIPEDGES 100 + +// !!! if these are changed, they must be changed in asm_draw.h too !!! +#define FULLY_CLIPPED_CACHED 0x80000000 +#define FRAMECOUNT_MASK 0x7FFFFFFF + +unsigned int cacheoffset; + +int c_faceclip; // number of faces clipped + + +clipplane_t *entity_clipplanes; +clipplane_t view_clipplanes[4]; +clipplane_t world_clipplanes[16]; + +medge_t *r_pedge; + +qboolean r_leftclipped, r_rightclipped; +static qboolean makeleftedge, makerightedge; +qboolean r_nearzionly; + +int sintable[1280]; +int intsintable[1280]; +int blanktable[1280]; // PGM + +mvertex_t r_leftenter, r_leftexit; +mvertex_t r_rightenter, r_rightexit; + +typedef struct +{ + float u,v; + int ceilv; +} evert_t; + +int r_emitted; +float r_nearzi; +float r_u1, r_v1, r_lzi1; +int r_ceilv1; + +qboolean r_lastvertvalid; +int r_skyframe; + +msurface_t *r_skyfaces; +mplane_t r_skyplanes[6]; +mtexinfo_t r_skytexinfo[6]; +mvertex_t *r_skyverts; +medge_t *r_skyedges; +int *r_skysurfedges; + +// I just copied this data from a box map... +int skybox_planes[12] = {2,-128, 0,-128, 2,128, 1,128, 0,128, 1,-128}; + +int box_surfedges[24] = { 1,2,3,4, -1,5,6,7, 8,9,-6,10, -2,-7,-9,11, + 12,-3,-11,-8, -12,-10,-5,-4}; +int box_edges[24] = { 1,2, 2,3, 3,4, 4,1, 1,5, 5,6, 6,2, 7,8, 8,6, 5,7, 8,3, 7,4}; + +int box_faces[6] = {0,0,2,2,2,0}; + +vec3_t box_vecs[6][2] = { + { {0,-1,0}, {-1,0,0} }, + { {0,1,0}, {0,0,-1} }, + { {0,-1,0}, {1,0,0} }, + { {1,0,0}, {0,0,-1} }, + { {0,-1,0}, {0,0,-1} }, + { {-1,0,0}, {0,0,-1} } +}; + +float box_verts[8][3] = { + {-1,-1,-1}, + {-1,1,-1}, + {1,1,-1}, + {1,-1,-1}, + {-1,-1,1}, + {-1,1,1}, + {1,-1,1}, + {1,1,1} +}; + +// down, west, up, north, east, south +// {"rt", "bk", "lf", "ft", "up", "dn"}; +#if 0 +/* +================ +R_InitSkyBox + +================ +*/ +void R_InitSkyBox (void) +{ + int i; + extern model_t *loadmodel; + + r_skyfaces = loadmodel->surfaces + loadmodel->numsurfaces; + loadmodel->numsurfaces += 6; + r_skyverts = loadmodel->vertexes + loadmodel->numvertexes; + loadmodel->numvertexes += 8; + r_skyedges = loadmodel->edges + loadmodel->numedges; + loadmodel->numedges += 12; + r_skysurfedges = loadmodel->surfedges + loadmodel->numsurfedges; + loadmodel->numsurfedges += 24; + if (loadmodel->numsurfaces > MAX_MAP_FACES + || loadmodel->numvertexes > MAX_MAP_VERTS + || loadmodel->numedges > MAX_MAP_EDGES) + ri.Sys_Error (ERR_DROP, "InitSkyBox: map overflow"); + + memset (r_skyfaces, 0, 6*sizeof(*r_skyfaces)); + for (i=0 ; i<6 ; i++) + { + r_skyplanes[i].normal[skybox_planes[i*2]] = 1; + r_skyplanes[i].dist = skybox_planes[i*2+1]; + + VectorCopy (box_vecs[i][0], r_skytexinfo[i].vecs[0]); + VectorCopy (box_vecs[i][1], r_skytexinfo[i].vecs[1]); + + r_skyfaces[i].plane = &r_skyplanes[i]; + r_skyfaces[i].numedges = 4; + r_skyfaces[i].flags = box_faces[i] | SURF_DRAWSKYBOX; + r_skyfaces[i].firstedge = loadmodel->numsurfedges-24+i*4; + r_skyfaces[i].texinfo = &r_skytexinfo[i]; + r_skyfaces[i].texturemins[0] = -128; + r_skyfaces[i].texturemins[1] = -128; + r_skyfaces[i].extents[0] = 256; + r_skyfaces[i].extents[1] = 256; + } + + for (i=0 ; i<24 ; i++) + if (box_surfedges[i] > 0) + r_skysurfedges[i] = loadmodel->numedges-13 + box_surfedges[i]; + else + r_skysurfedges[i] = - (loadmodel->numedges-13 + -box_surfedges[i]); + + for(i=0 ; i<12 ; i++) + { + r_skyedges[i].v[0] = loadmodel->numvertexes-9+box_edges[i*2+0]; + r_skyedges[i].v[1] = loadmodel->numvertexes-9+box_edges[i*2+1]; + r_skyedges[i].cachededgeoffset = 0; + } +} + +/* +================ +R_EmitSkyBox +================ +*/ +void R_EmitSkyBox (void) +{ + int i, j; + int oldkey; + + if (insubmodel) + return; // submodels should never have skies + if (r_skyframe == r_framecount) + return; // already set this frame + + r_skyframe = r_framecount; + + // set the eight fake vertexes + for (i=0 ; i<8 ; i++) + for (j=0 ; j<3 ; j++) + r_skyverts[i].position[j] = r_origin[j] + box_verts[i][j]*128; + + // set the six fake planes + for (i=0 ; i<6 ; i++) + if (skybox_planes[i*2+1] > 0) + r_skyplanes[i].dist = r_origin[skybox_planes[i*2]]+128; + else + r_skyplanes[i].dist = r_origin[skybox_planes[i*2]]-128; + + // fix texture offseets + for (i=0 ; i<6 ; i++) + { + r_skytexinfo[i].vecs[0][3] = -DotProduct (r_origin, r_skytexinfo[i].vecs[0]); + r_skytexinfo[i].vecs[1][3] = -DotProduct (r_origin, r_skytexinfo[i].vecs[1]); + } + + // emit the six faces + oldkey = r_currentkey; + r_currentkey = 0x7ffffff0; + for (i=0 ; i<6 ; i++) + { + R_RenderFace (r_skyfaces + i, 15); + } + r_currentkey = oldkey; // bsp sorting order +} + +#endif +#if !id386 + +/* +================ +R_EmitEdge +================ +*/ +void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) +{ + edge_t *edge, *pcheck; + int u_check; + float u, u_step; + vec3_t local, transformed; + float *world; + int v, v2, ceilv0; + float scale, lzi0, u0, v0; + int side; + + if (r_lastvertvalid) + { + u0 = r_u1; + v0 = r_v1; + lzi0 = r_lzi1; + ceilv0 = r_ceilv1; + } + else + { + world = &pv0->position[0]; + + // transform and project + VectorSubtract (world, modelorg, local); + TransformVector (local, transformed); + + if (transformed[2] < NEAR_CLIP) + transformed[2] = NEAR_CLIP; + + lzi0 = 1.0 / transformed[2]; + + // FIXME: build x/yscale into transform? + scale = xscale * lzi0; + u0 = (xcenter + scale*transformed[0]); + if (u0 < 0) + u0 = 0; + if (u0 > gpGlobals->width) + u0 = gpGlobals->width; + + scale = yscale * lzi0; + v0 = (ycenter - scale*transformed[1]); + if (v0 < 0) + v0 = 0; + if (v0 > gpGlobals->height) + v0 = gpGlobals->height; + + ceilv0 = (int) ceil(v0); + } + + world = &pv1->position[0]; + +// transform and project + VectorSubtract (world, modelorg, local); + TransformVector (local, transformed); + + if (transformed[2] < NEAR_CLIP) + transformed[2] = NEAR_CLIP; + + r_lzi1 = 1.0 / transformed[2]; + + scale = xscale * r_lzi1; + r_u1 = (xcenter + scale*transformed[0]); + if (r_u1 < 0) + r_u1 = 0; + if (r_u1 > gpGlobals->width) + r_u1 = gpGlobals->width; + + scale = yscale * r_lzi1; + r_v1 = (ycenter - scale*transformed[1]); + if (r_v1 < 0) + r_v1 = 0; + if (r_v1 > gpGlobals->height) + r_v1 = gpGlobals->height; + + if (r_lzi1 > lzi0) + lzi0 = r_lzi1; + + if (lzi0 > r_nearzi) // for mipmap finding + r_nearzi = lzi0; + +// for right edges, all we want is the effect on 1/z + if (r_nearzionly) + return; + + r_emitted = 1; + + r_ceilv1 = (int) ceil(r_v1); + + +// create the edge + if (ceilv0 == r_ceilv1) + { + // we cache unclipped horizontal edges as fully clipped + if (cacheoffset != 0x7FFFFFFF) + { + cacheoffset = FULLY_CLIPPED_CACHED | + (r_framecount & FRAMECOUNT_MASK); + } + + return; // horizontal edge + } + + side = ceilv0 > r_ceilv1; + + edge = edge_p++; + + edge->owner = r_pedge; + + edge->nearzi = lzi0; + + if (side == 0) + { + // trailing edge (go from p1 to p2) + v = ceilv0; + v2 = r_ceilv1 - 1; + + edge->surfs[0] = surface_p - surfaces; + edge->surfs[1] = 0; + + u_step = ((r_u1 - u0) / (r_v1 - v0)); + u = u0 + ((float)v - v0) * u_step; + } + else + { + // leading edge (go from p2 to p1) + v2 = ceilv0 - 1; + v = r_ceilv1; + + edge->surfs[0] = 0; + edge->surfs[1] = surface_p - surfaces; + + u_step = ((u0 - r_u1) / (v0 - r_v1)); + u = r_u1 + ((float)v - r_v1) * u_step; + } + + edge->u_step = u_step*0x100000; + edge->u = u*0x100000 + 0xFFFFF; + +// we need to do this to avoid stepping off the edges if a very nearly +// horizontal edge is less than epsilon above a scan, and numeric error causes +// it to incorrectly extend to the scan, and the extension of the line goes off +// the edge of the screen +// FIXME: is this actually needed? +// if (edge->u < r_refdef.vrect_x_adj_shift20) +// edge->u = r_refdef.vrect_x_adj_shift20; +// if (edge->u > r_refdef.vrectright_adj_shift20) +// edge->u = r_refdef.vrectright_adj_shift20; + +// +// sort the edge in normally +// + u_check = edge->u; + if (edge->surfs[0]) + u_check++; // sort trailers after leaders + + if (!newedges[v] || newedges[v]->u >= u_check) + { + edge->next = newedges[v]; + newedges[v] = edge; + } + else + { + pcheck = newedges[v]; + while (pcheck->next && pcheck->next->u < u_check) + pcheck = pcheck->next; + edge->next = pcheck->next; + pcheck->next = edge; + } + + edge->nextremove = removeedges[v2]; + removeedges[v2] = edge; +} + + +/* +================ +R_ClipEdge +================ +*/ +void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip) +{ + float d0, d1, f; + mvertex_t clipvert; + + if (clip) + { + do + { + d0 = DotProduct (pv0->position, clip->normal) - clip->dist; + d1 = DotProduct (pv1->position, clip->normal) - clip->dist; + + if (d0 >= 0) + { + // point 0 is unclipped + if (d1 >= 0) + { + // both points are unclipped + continue; + } + + // only point 1 is clipped + + // we don't cache clipped edges + cacheoffset = 0x7FFFFFFF; + + f = d0 / (d0 - d1); + clipvert.position[0] = pv0->position[0] + + f * (pv1->position[0] - pv0->position[0]); + clipvert.position[1] = pv0->position[1] + + f * (pv1->position[1] - pv0->position[1]); + clipvert.position[2] = pv0->position[2] + + f * (pv1->position[2] - pv0->position[2]); + + if (clip->leftedge) + { + r_leftclipped = true; + r_leftexit = clipvert; + } + else if (clip->rightedge) + { + r_rightclipped = true; + r_rightexit = clipvert; + } + + R_ClipEdge (pv0, &clipvert, clip->next); + return; + } + else + { + // point 0 is clipped + if (d1 < 0) + { + // both points are clipped + // we do cache fully clipped edges + if (!r_leftclipped) + cacheoffset = FULLY_CLIPPED_CACHED | + (r_framecount & FRAMECOUNT_MASK); + return; + } + + // only point 0 is clipped + r_lastvertvalid = false; + + // we don't cache partially clipped edges + cacheoffset = 0x7FFFFFFF; + + f = d0 / (d0 - d1); + clipvert.position[0] = pv0->position[0] + + f * (pv1->position[0] - pv0->position[0]); + clipvert.position[1] = pv0->position[1] + + f * (pv1->position[1] - pv0->position[1]); + clipvert.position[2] = pv0->position[2] + + f * (pv1->position[2] - pv0->position[2]); + + if (clip->leftedge) + { + r_leftclipped = true; + r_leftenter = clipvert; + } + else if (clip->rightedge) + { + r_rightclipped = true; + r_rightenter = clipvert; + } + + R_ClipEdge (&clipvert, pv1, clip->next); + return; + } + } while ((clip = clip->next) != NULL); + } + +// add the edge + R_EmitEdge (pv0, pv1); +} + +#endif // !id386 + + +/* +================ +R_EmitCachedEdge +================ +*/ +void R_EmitCachedEdge (void) +{ + edge_t *pedge_t; + + pedge_t = (edge_t *)((unsigned long)r_edges + r_pedge->cachededgeoffset); + + if (!pedge_t->surfs[0]) + pedge_t->surfs[0] = surface_p - surfaces; + else + pedge_t->surfs[1] = surface_p - surfaces; + + if (pedge_t->nearzi > r_nearzi) // for mipmap finding + r_nearzi = pedge_t->nearzi; + + r_emitted = 1; +} + + +/* +================ +R_RenderFace +================ +*/ +void R_RenderFace (msurface_t *fa, int clipflags) +{ + int i, lindex; + unsigned mask; + mplane_t *pplane; + float distinv; + vec3_t p_normal; + medge_t *pedges, tedge; + clipplane_t *pclip; + + // translucent surfaces are not drawn by the edge renderer +/* if (fa->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) + { + fa->nextalphasurface = r_alpha_surfaces; + r_alpha_surfaces = fa; + return; + }*/ + + // sky surfaces encountered in the world will cause the + // environment box surfaces to be emited +/* if ( fa->texinfo->flags & SURF_SKY ) + { + R_EmitSkyBox (); + return; + }*/ + +// skip out if no more surfs + if ((surface_p) >= surf_max) + { + // r_outofsurfaces++; + return; + } + +// ditto if not enough edges left, or switch to auxedges if possible + if ((edge_p + fa->numedges + 4) >= edge_max) + { + //r_outofedges += fa->numedges; + return; + } + + c_faceclip++; + +// set up clip planes + pclip = NULL; + + for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1) + { + if (clipflags & mask) + { + view_clipplanes[i].next = pclip; + pclip = &view_clipplanes[i]; + } + } + +// push the edges through + r_emitted = 0; + r_nearzi = 0; + r_nearzionly = false; + makeleftedge = makerightedge = false; + pedges = RI.currentmodel->edges; + r_lastvertvalid = false; + + for (i=0 ; inumedges ; i++) + { + lindex = RI.currentmodel->surfedges[fa->firstedge + i]; + + if (lindex > 0) + { + r_pedge = &pedges[lindex]; + + // if the edge is cached, we can just reuse the edge + //if (!insubmodel) + { + if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) + { + if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) == + r_framecount) + { + r_lastvertvalid = false; + continue; + } + } + else + { + if ((((unsigned long)edge_p - (unsigned long)r_edges) > + r_pedge->cachededgeoffset) && + (((edge_t *)((unsigned long)r_edges + + r_pedge->cachededgeoffset))->owner == r_pedge)) + { + R_EmitCachedEdge (); + r_lastvertvalid = false; + continue; + } + } + } + + // assume it's cacheable + cacheoffset = (byte *)edge_p - (byte *)r_edges; + r_leftclipped = r_rightclipped = false; + R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[0]], + &r_pcurrentvertbase[r_pedge->v[1]], + pclip); + r_pedge->cachededgeoffset = cacheoffset; + + if (r_leftclipped) + makeleftedge = true; + if (r_rightclipped) + makerightedge = true; + r_lastvertvalid = true; + } + else + { + lindex = -lindex; + r_pedge = &pedges[lindex]; + // if the edge is cached, we can just reuse the edge + //if (!insubmodel) + { + if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) + { + if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) == + r_framecount) + { + r_lastvertvalid = false; + continue; + } + } + else + { + // it's cached if the cached edge is valid and is owned + // by this medge_t + if ((((unsigned long)edge_p - (unsigned long)r_edges) > + r_pedge->cachededgeoffset) && + (((edge_t *)((unsigned long)r_edges + + r_pedge->cachededgeoffset))->owner == r_pedge)) + { + R_EmitCachedEdge (); + r_lastvertvalid = false; + continue; + } + } + } + + // assume it's cacheable + cacheoffset = (byte *)edge_p - (byte *)r_edges; + r_leftclipped = r_rightclipped = false; + R_ClipEdge (&r_pcurrentvertbase[r_pedge->v[1]], + &r_pcurrentvertbase[r_pedge->v[0]], + pclip); + r_pedge->cachededgeoffset = cacheoffset; + + if (r_leftclipped) + makeleftedge = true; + if (r_rightclipped) + makerightedge = true; + r_lastvertvalid = true; + } + } + +// if there was a clip off the left edge, add that edge too +// FIXME: faster to do in screen space? +// FIXME: share clipped edges? + if (makeleftedge) + { + r_pedge = &tedge; + r_lastvertvalid = false; + R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next); + } + +// if there was a clip off the right edge, get the right r_nearzi + if (makerightedge) + { + r_pedge = &tedge; + r_lastvertvalid = false; + r_nearzionly = true; + R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next); + } + +// if no edges made it out, return without posting the surface + if (!r_emitted) + return; + +// r_polycount++; + + surface_p->msurf = fa; + surface_p->nearzi = r_nearzi; + surface_p->flags = fa->flags; + //surface_p->insubmodel = insubmodel; + surface_p->spanstate = 0; + surface_p->entity = RI.currententity; + surface_p->key = r_currentkey++; + surface_p->spans = NULL; + + pplane = fa->plane; +// FIXME: cache this? + TransformVector (pplane->normal, p_normal); +// FIXME: cache this? + distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal)); + + surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; + surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; + surface_p->d_ziorigin = p_normal[2] * distinv - + xcenter * surface_p->d_zistepu - + ycenter * surface_p->d_zistepv; + + surface_p++; +} + + +/* +================ +R_RenderBmodelFace +================ +*/ +void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf) +{ + int i; + unsigned mask; + mplane_t *pplane; + float distinv; + vec3_t p_normal; + medge_t tedge; + clipplane_t *pclip; + + /*if (psurf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) + { + psurf->nextalphasurface = r_alpha_surfaces; + r_alpha_surfaces = psurf; + return; + }*/ + +// skip out if no more surfs + if (surface_p >= surf_max) + { + //r_outofsurfaces++; + return; + } + +// ditto if not enough edges left, or switch to auxedges if possible + if ((edge_p + psurf->numedges + 4) >= edge_max) + { + //r_outofedges += psurf->numedges; + return; + } + + c_faceclip++; + +// this is a dummy to give the caching mechanism someplace to write to + r_pedge = &tedge; + +// set up clip planes + pclip = NULL; + + for (i=3, mask = 0x08 ; i>=0 ; i--, mask >>= 1) + { + if (r_clipflags & mask) + { + view_clipplanes[i].next = pclip; + pclip = &view_clipplanes[i]; + } + } + +// push the edges through + r_emitted = 0; + r_nearzi = 0; + r_nearzionly = false; + makeleftedge = makerightedge = false; +// FIXME: keep clipped bmodel edges in clockwise order so last vertex caching +// can be used? + r_lastvertvalid = false; + + for ( ; pedges ; pedges = pedges->pnext) + { + r_leftclipped = r_rightclipped = false; + R_ClipEdge (pedges->v[0], pedges->v[1], pclip); + + if (r_leftclipped) + makeleftedge = true; + if (r_rightclipped) + makerightedge = true; + } + +// if there was a clip off the left edge, add that edge too +// FIXME: faster to do in screen space? +// FIXME: share clipped edges? + if (makeleftedge) + { + r_pedge = &tedge; + R_ClipEdge (&r_leftexit, &r_leftenter, pclip->next); + } + +// if there was a clip off the right edge, get the right r_nearzi + if (makerightedge) + { + r_pedge = &tedge; + r_nearzionly = true; + R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next); + } + +// if no edges made it out, return without posting the surface + if (!r_emitted) + return; + + //r_polycount++; + + surface_p->msurf = psurf; + surface_p->nearzi = r_nearzi; + surface_p->flags = psurf->flags; + surface_p->insubmodel = true; + surface_p->spanstate = 0; + surface_p->entity = RI.currententity; + surface_p->key = r_currentbkey; + surface_p->spans = NULL; + + pplane = psurf->plane; +// FIXME: cache this? + TransformVector (pplane->normal, p_normal); +// FIXME: cache this? + distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal)); + + surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; + surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; + surface_p->d_ziorigin = p_normal[2] * distinv - + xcenter * surface_p->d_zistepu - + ycenter * surface_p->d_zistepv; + + surface_p++; +} + diff --git a/r_scan.c b/r_scan.c new file mode 100644 index 00000000..5aaece7f --- /dev/null +++ b/r_scan.c @@ -0,0 +1,593 @@ +/* +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. + +*/ +// d_scan.c +// +// Portable C scan-level rasterization code, all pixel depths. + +#include "r_local.h" + +unsigned char *r_turb_pbase, *r_turb_pdest; +fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep; +int *r_turb_turb; +int r_turb_spancount; + +void D_DrawTurbulent8Span (void); + + +/* +============= +D_WarpScreen + +this performs a slight compression of the screen at the same time as +the sine warp, to keep the edges from wrapping +============= +*/ +void D_WarpScreen (void) +{ +#if 0 + int w, h; + int u,v, u2, v2; + byte *dest; + int *turb; + int *col; + byte **row; + + static int cached_width, cached_height; + static byte *rowptr[1200+AMP2*2]; + static int column[1600+AMP2*2]; + + // + // these are constant over resolutions, and can be saved + // + w = r_newrefdef.width; + h = r_newrefdef.height; + if (w != cached_width || h != cached_height) + { + cached_width = w; + cached_height = h; + for (v=0 ; v>16)&(CYCLE-1)])>>16)&63; + tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63; + *r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb); + r_turb_s += r_turb_sstep; + r_turb_t += r_turb_tstep; + } while (--r_turb_spancount > 0); +} + +#endif // !id386 + + +/* +============= +Turbulent8 +============= +*/ +void Turbulent8 (espan_t *pspan) +{ + int count; + fixed16_t snext, tnext; + float sdivz, tdivz, zi, z, du, dv, spancountminus1; + float sdivz16stepu, tdivz16stepu, zi16stepu; + + r_turb_turb = sintable + ((int)(gpGlobals->time*SPEED)&(CYCLE-1)); + + r_turb_sstep = 0; // keep compiler happy + r_turb_tstep = 0; // ditto + + r_turb_pbase = (unsigned char *)cacheblock; + + sdivz16stepu = d_sdivzstepu * 16; + tdivz16stepu = d_tdivzstepu * 16; + zi16stepu = d_zistepu * 16; + + do + { + r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer + + (r_screenwidth * pspan->v) + pspan->u); + + count = pspan->count; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float)pspan->u; + dv = (float)pspan->v; + + sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; + tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; + zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + + r_turb_s = (int)(sdivz * z) + sadjust; + if (r_turb_s > bbextents) + r_turb_s = bbextents; + else if (r_turb_s < 0) + r_turb_s = 0; + + r_turb_t = (int)(tdivz * z) + tadjust; + if (r_turb_t > bbextentt) + r_turb_t = bbextentt; + else if (r_turb_t < 0) + r_turb_t = 0; + + do + { + // calculate s and t at the far end of the span + if (count >= 16) + r_turb_spancount = 16; + else + r_turb_spancount = count; + + count -= r_turb_spancount; + + if (count) + { + // calculate s/z, t/z, zi->fixed s and t at far end of span, + // calculate s and t steps across span by shifting + sdivz += sdivz16stepu; + tdivz += tdivz16stepu; + zi += zi16stepu; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 16) + snext = 16; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 16) + tnext = 16; // guard against round-off error on <0 steps + + r_turb_sstep = (snext - r_turb_s) >> 4; + r_turb_tstep = (tnext - r_turb_t) >> 4; + } + else + { + // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so + // can't step off polygon), clamp, calculate s and t steps across + // span by division, biasing steps low so we don't run off the + // texture + spancountminus1 = (float)(r_turb_spancount - 1); + sdivz += d_sdivzstepu * spancountminus1; + tdivz += d_tdivzstepu * spancountminus1; + zi += d_zistepu * spancountminus1; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 16) + snext = 16; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 16) + tnext = 16; // guard against round-off error on <0 steps + + if (r_turb_spancount > 1) + { + r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1); + r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1); + } + } + + r_turb_s = r_turb_s & ((CYCLE<<16)-1); + r_turb_t = r_turb_t & ((CYCLE<<16)-1); + + D_DrawTurbulent8Span (); + + r_turb_s = snext; + r_turb_t = tnext; + + } while (count > 0); + + } while ((pspan = pspan->pnext) != NULL); +} + +//==================== +//PGM +/* +============= +NonTurbulent8 - this is for drawing scrolling textures. they're warping water textures + but the turbulence is automatically 0. +============= +*/ +void NonTurbulent8 (espan_t *pspan) +{ + int count; + fixed16_t snext, tnext; + float sdivz, tdivz, zi, z, du, dv, spancountminus1; + float sdivz16stepu, tdivz16stepu, zi16stepu; + +// r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1)); + r_turb_turb = blanktable; + + r_turb_sstep = 0; // keep compiler happy + r_turb_tstep = 0; // ditto + + r_turb_pbase = (unsigned char *)cacheblock; + + sdivz16stepu = d_sdivzstepu * 16; + tdivz16stepu = d_tdivzstepu * 16; + zi16stepu = d_zistepu * 16; + + do + { + r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer + + (r_screenwidth * pspan->v) + pspan->u); + + count = pspan->count; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float)pspan->u; + dv = (float)pspan->v; + + sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; + tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; + zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + + r_turb_s = (int)(sdivz * z) + sadjust; + if (r_turb_s > bbextents) + r_turb_s = bbextents; + else if (r_turb_s < 0) + r_turb_s = 0; + + r_turb_t = (int)(tdivz * z) + tadjust; + if (r_turb_t > bbextentt) + r_turb_t = bbextentt; + else if (r_turb_t < 0) + r_turb_t = 0; + + do + { + // calculate s and t at the far end of the span + if (count >= 16) + r_turb_spancount = 16; + else + r_turb_spancount = count; + + count -= r_turb_spancount; + + if (count) + { + // calculate s/z, t/z, zi->fixed s and t at far end of span, + // calculate s and t steps across span by shifting + sdivz += sdivz16stepu; + tdivz += tdivz16stepu; + zi += zi16stepu; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 16) + snext = 16; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 16) + tnext = 16; // guard against round-off error on <0 steps + + r_turb_sstep = (snext - r_turb_s) >> 4; + r_turb_tstep = (tnext - r_turb_t) >> 4; + } + else + { + // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so + // can't step off polygon), clamp, calculate s and t steps across + // span by division, biasing steps low so we don't run off the + // texture + spancountminus1 = (float)(r_turb_spancount - 1); + sdivz += d_sdivzstepu * spancountminus1; + tdivz += d_tdivzstepu * spancountminus1; + zi += d_zistepu * spancountminus1; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 16) + snext = 16; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 16) + tnext = 16; // guard against round-off error on <0 steps + + if (r_turb_spancount > 1) + { + r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1); + r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1); + } + } + + r_turb_s = r_turb_s & ((CYCLE<<16)-1); + r_turb_t = r_turb_t & ((CYCLE<<16)-1); + + D_DrawTurbulent8Span (); + + r_turb_s = snext; + r_turb_t = tnext; + + } while (count > 0); + + } while ((pspan = pspan->pnext) != NULL); +} +//PGM +//==================== + + +#if !id386 + +/* +============= +D_DrawSpans16 + + FIXME: actually make this subdivide by 16 instead of 8!!! +============= +*/ +void D_DrawSpans16 (espan_t *pspan) +{ + int count, spancount; + unsigned char *pbase, *pdest; + fixed16_t s, t, snext, tnext, sstep, tstep; + float sdivz, tdivz, zi, z, du, dv, spancountminus1; + float sdivz8stepu, tdivz8stepu, zi8stepu; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + pbase = (unsigned char *)cacheblock; + + sdivz8stepu = d_sdivzstepu * 8; + tdivz8stepu = d_tdivzstepu * 8; + zi8stepu = d_zistepu * 8; + + do + { + pdest = (unsigned char *)((byte *)d_viewbuffer + + (r_screenwidth * pspan->v) + pspan->u); + + count = pspan->count; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float)pspan->u; + dv = (float)pspan->v; + + sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; + tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; + zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + + s = (int)(sdivz * z) + sadjust; + if (s > bbextents) + s = bbextents; + else if (s < 0) + s = 0; + + t = (int)(tdivz * z) + tadjust; + if (t > bbextentt) + t = bbextentt; + else if (t < 0) + t = 0; + + do + { + // calculate s and t at the far end of the span + if (count >= 8) + spancount = 8; + else + spancount = count; + + count -= spancount; + + if (count) + { + // calculate s/z, t/z, zi->fixed s and t at far end of span, + // calculate s and t steps across span by shifting + sdivz += sdivz8stepu; + tdivz += tdivz8stepu; + zi += zi8stepu; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on <0 steps + + sstep = (snext - s) >> 3; + tstep = (tnext - t) >> 3; + } + else + { + // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so + // can't step off polygon), clamp, calculate s and t steps across + // span by division, biasing steps low so we don't run off the + // texture + spancountminus1 = (float)(spancount - 1); + sdivz += d_sdivzstepu * spancountminus1; + tdivz += d_tdivzstepu * spancountminus1; + zi += d_zistepu * spancountminus1; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on <0 steps + + if (spancount > 1) + { + sstep = (snext - s) / (spancount - 1); + tstep = (tnext - t) / (spancount - 1); + } + } + + do + { + *pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth); + s += sstep; + t += tstep; + } while (--spancount > 0); + + s = snext; + t = tnext; + + } while (count > 0); + + } while ((pspan = pspan->pnext) != NULL); +} + +#endif + + +#if !id386 + +/* +============= +D_DrawZSpans +============= +*/ +void D_DrawZSpans (espan_t *pspan) +{ + int count, doublecount, izistep; + int izi; + short *pdest; + unsigned ltemp; + float zi; + float du, dv; + +// FIXME: check for clamping/range problems +// we count on FP exceptions being turned off to avoid range problems + izistep = (int)(d_zistepu * 0x8000 * 0x10000); + + do + { + pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; + + count = pspan->count; + + // calculate the initial 1/z + du = (float)pspan->u; + dv = (float)pspan->v; + + zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; + // we count on FP exceptions being turned off to avoid range problems + izi = (int)(zi * 0x8000 * 0x10000); + + if ((long)pdest & 0x02) + { + *pdest++ = (short)(izi >> 16); + izi += izistep; + count--; + } + + if ((doublecount = count >> 1) > 0) + { + do + { + ltemp = izi >> 16; + izi += izistep; + ltemp |= izi & 0xFFFF0000; + izi += izistep; + *(int *)pdest = ltemp; + pdest += 2; + } while (--doublecount > 0); + } + + if (count & 1) + *pdest = (short)(izi >> 16); + + } while ((pspan = pspan->pnext) != NULL); +} + +#endif + diff --git a/r_surf.c b/r_surf.c new file mode 100644 index 00000000..cb17b9d1 --- /dev/null +++ b/r_surf.c @@ -0,0 +1,753 @@ +/* +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. + +*/ +// r_surf.c: surface-related refresh code + +#include "r_local.h" + +drawsurf_t r_drawsurf; + +int lightleft, sourcesstep, blocksize, sourcetstep; +int lightdelta, lightdeltastep; +int lightright, lightleftstep, lightrightstep, blockdivshift; +unsigned blockdivmask; +void *prowdestbase; +unsigned char *pbasesource; +int surfrowbytes; // used by ASM files +unsigned *r_lightptr; +int r_stepback; +int r_lightwidth; +int r_numhblocks, r_numvblocks; +unsigned char *r_source, *r_sourcemax; + +void R_DrawSurfaceBlock8_mip0 (void); +void R_DrawSurfaceBlock8_mip1 (void); +void R_DrawSurfaceBlock8_mip2 (void); +void R_DrawSurfaceBlock8_mip3 (void); + +static void (*surfmiptable[4])(void) = { + R_DrawSurfaceBlock8_mip0, + R_DrawSurfaceBlock8_mip1, + R_DrawSurfaceBlock8_mip2, + R_DrawSurfaceBlock8_mip3 +}; + +void R_BuildLightMap (void); +extern unsigned blocklights[1024]; // allow some very large lightmaps + +float surfscale; +qboolean r_cache_thrash; // set if surface cache is thrashing + +int sc_size; +surfcache_t *sc_rover, *sc_base; + +static int rtable[MOD_FRAMES][MOD_FRAMES]; + +void R_InitRandomTable( void ) +{ + int tu, tv; + + // make random predictable + gEngfuncs.COM_SetRandomSeed( 255 ); + + for( tu = 0; tu < MOD_FRAMES; tu++ ) + { + for( tv = 0; tv < MOD_FRAMES; tv++ ) + { + rtable[tu][tv] = gEngfuncs.COM_RandomLong( 0, 0x7FFF ); + } + } + + gEngfuncs.COM_SetRandomSeed( 0 ); +} + +/* +=============== +R_TextureAnim + +Returns the proper texture for a given time and base texture, do not process random tiling +=============== +*/ +texture_t *R_TextureAnim( texture_t *b ) +{ + texture_t *base = b; + int count, reletive; + + if( RI.currententity->curstate.frame ) + { + if( base->alternate_anims ) + base = base->alternate_anims; + } + + if( !base->anim_total ) + return base; + if( base->name[0] == '-' ) + { + return b; // already tiled + } + else + { + int speed; + + // Quake1 textures uses 10 frames per second + if( FBitSet( R_GetTexture( base->gl_texturenum )->flags, TF_QUAKEPAL )) + speed = 10; + else speed = 20; + + reletive = (int)(gpGlobals->time * speed) % base->anim_total; + } + + + count = 0; + + while( base->anim_min > reletive || base->anim_max <= reletive ) + { + base = base->anim_next; + + if( !base || ++count > MOD_FRAMES ) + return b; + } + + return base; +} + +/* +=============== +R_TextureAnimation + +Returns the proper texture for a given time and surface +=============== +*/ +texture_t *R_TextureAnimation( msurface_t *s ) +{ + texture_t *base = s->texinfo->texture; + int count, reletive; + + if( RI.currententity && RI.currententity->curstate.frame ) + { + if( base->alternate_anims ) + base = base->alternate_anims; + } + + if( !base->anim_total ) + return base; + + if( base->name[0] == '-' ) + { + int tx = (int)((s->texturemins[0] + (base->width << 16)) / base->width) % MOD_FRAMES; + int ty = (int)((s->texturemins[1] + (base->height << 16)) / base->height) % MOD_FRAMES; + + reletive = rtable[tx][ty] % base->anim_total; + } + else + { + int speed; + + // Quake1 textures uses 10 frames per second + if( FBitSet( R_GetTexture( base->gl_texturenum )->flags, TF_QUAKEPAL )) + speed = 10; + else speed = 20; + + reletive = (int)(gpGlobals->time * speed) % base->anim_total; + } + + count = 0; + + while( base->anim_min > reletive || base->anim_max <= reletive ) + { + base = base->anim_next; + + if( !base || ++count > MOD_FRAMES ) + return s->texinfo->texture; + } + + return base; +} + + +/* +=============== +R_DrawSurface +=============== +*/ +void R_DrawSurface (void) +{ + unsigned char *basetptr; + int smax, tmax, twidth; + int u; + int soffset, basetoffset, texwidth; + int horzblockstep; + unsigned char *pcolumndest; + void (*pblockdrawer)(void); + image_t *mt; + + surfrowbytes = r_drawsurf.rowbytes; + + mt = r_drawsurf.image; + + r_source = mt->pixels[r_drawsurf.surfmip]; + +// the fractional light values should range from 0 to (VID_GRADES - 1) << 16 +// from a source range of 0 - 255 + + texwidth = mt->width >> r_drawsurf.surfmip; + + blocksize = 16 >> r_drawsurf.surfmip; + blockdivshift = 4 - r_drawsurf.surfmip; + blockdivmask = (1 << blockdivshift) - 1; + + r_lightwidth = (r_drawsurf.surf->extents[0]>>4)+1; + + r_numhblocks = r_drawsurf.surfwidth >> blockdivshift; + r_numvblocks = r_drawsurf.surfheight >> blockdivshift; + +//============================== + + pblockdrawer = surfmiptable[r_drawsurf.surfmip]; +// TODO: only needs to be set when there is a display settings change + horzblockstep = blocksize; + + smax = mt->width >> r_drawsurf.surfmip; + twidth = texwidth; + tmax = mt->height >> r_drawsurf.surfmip; + sourcetstep = texwidth; + r_stepback = tmax * twidth; + + r_sourcemax = r_source + (tmax * smax); + + soffset = r_drawsurf.surf->texturemins[0]; + basetoffset = r_drawsurf.surf->texturemins[1]; + +// << 16 components are to guarantee positive values for % + soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax; + basetptr = &r_source[((((basetoffset >> r_drawsurf.surfmip) + + (tmax << 16)) % tmax) * twidth)]; + + pcolumndest = r_drawsurf.surfdat; + + for (u=0 ; u= smax) + soffset = 0; + + pcolumndest += horzblockstep; + } +} + + +//============================================================================= + +#if !id386 + +/* +================ +R_DrawSurfaceBlock8_mip0 +================ +*/ +void R_DrawSurfaceBlock8_mip0 (void) +{ + int v, i, b, lightstep, lighttemp, light; + unsigned char pix, *psource, *prowdest; + + psource = pbasesource; + prowdest = prowdestbase; + + for (v=0 ; v> 4; + lightrightstep = (r_lightptr[1] - lightright) >> 4; + + for (i=0 ; i<16 ; i++) + { + lighttemp = lightleft - lightright; + lightstep = lighttemp >> 4; + + light = lightright; + + for (b=15; b>=0; b--) + { + pix = psource[b]; + prowdest[b] = ((unsigned char *)vid.colormap) + [(light & 0xFF00) + pix]; + light += lightstep; + } + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += surfrowbytes; + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + + +/* +================ +R_DrawSurfaceBlock8_mip1 +================ +*/ +void R_DrawSurfaceBlock8_mip1 (void) +{ + int v, i, b, lightstep, lighttemp, light; + unsigned char pix, *psource, *prowdest; + + psource = pbasesource; + prowdest = prowdestbase; + + for (v=0 ; v> 3; + lightrightstep = (r_lightptr[1] - lightright) >> 3; + + for (i=0 ; i<8 ; i++) + { + lighttemp = lightleft - lightright; + lightstep = lighttemp >> 3; + + light = lightright; + + for (b=7; b>=0; b--) + { + pix = psource[b]; + prowdest[b] = ((unsigned char *)vid.colormap) + [(light & 0xFF00) + pix]; + light += lightstep; + } + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += surfrowbytes; + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + + +/* +================ +R_DrawSurfaceBlock8_mip2 +================ +*/ +void R_DrawSurfaceBlock8_mip2 (void) +{ + int v, i, b, lightstep, lighttemp, light; + unsigned char pix, *psource, *prowdest; + + psource = pbasesource; + prowdest = prowdestbase; + + for (v=0 ; v> 2; + lightrightstep = (r_lightptr[1] - lightright) >> 2; + + for (i=0 ; i<4 ; i++) + { + lighttemp = lightleft - lightright; + lightstep = lighttemp >> 2; + + light = lightright; + + for (b=3; b>=0; b--) + { + pix = psource[b]; + prowdest[b] = ((unsigned char *)vid.colormap) + [(light & 0xFF00) + pix]; + light += lightstep; + } + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += surfrowbytes; + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + + +/* +================ +R_DrawSurfaceBlock8_mip3 +================ +*/ +void R_DrawSurfaceBlock8_mip3 (void) +{ + int v, i, b, lightstep, lighttemp, light; + unsigned char pix, *psource, *prowdest; + + psource = pbasesource; + prowdest = prowdestbase; + + for (v=0 ; v> 1; + lightrightstep = (r_lightptr[1] - lightright) >> 1; + + for (i=0 ; i<2 ; i++) + { + lighttemp = lightleft - lightright; + lightstep = lighttemp >> 1; + + light = lightright; + + for (b=1; b>=0; b--) + { + pix = psource[b]; + prowdest[b] = ((unsigned char *)vid.colormap) + [(light & 0xFF00) + pix]; + light += lightstep; + } + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += surfrowbytes; + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + +#endif + + +//============================================================================ + + +/* +================ +R_InitCaches + +================ +*/ +void R_InitCaches (void) +{ + int size; + int pix; + + // calculate size to allocate + if (sw_surfcacheoverride->value) + { + size = sw_surfcacheoverride->value; + } + else + { + size = SURFCACHE_SIZE_AT_320X240; + + pix = vid.width*vid.height; + if (pix > 64000) + size += (pix-64000)*3; + } + + // round up to page size + size = (size + 8191) & ~8191; + + gEngfuncs.Con_Printf ("%ik surface cache\n", size/1024); + + sc_size = size; + sc_base = (surfcache_t *)malloc(size); + sc_rover = sc_base; + + sc_base->next = NULL; + sc_base->owner = NULL; + sc_base->size = sc_size; +} + + +/* +================== +D_FlushCaches +================== +*/ +void D_FlushCaches (void) +{ + surfcache_t *c; + + if (!sc_base) + return; + + for (c = sc_base ; c ; c = c->next) + { + if (c->owner) + *c->owner = NULL; + } + + sc_rover = sc_base; + sc_base->next = NULL; + sc_base->owner = NULL; + sc_base->size = sc_size; +} + +/* +================= +D_SCAlloc +================= +*/ +surfcache_t *D_SCAlloc (int width, int size) +{ + surfcache_t *new; + qboolean wrapped_this_time; + + if ((width < 0) || (width > 256)) + gEngfuncs.Host_Error ("D_SCAlloc: bad cache width %d\n", width); + + if ((size <= 0) || (size > 0x10000)) + gEngfuncs.Host_Error ("D_SCAlloc: bad cache size %d\n", size); + + size = (int)&((surfcache_t *)0)->data[size]; + size = (size + 3) & ~3; + if (size > sc_size) + gEngfuncs.Host_Error ("D_SCAlloc: %i > cache size of %i",size, sc_size); + +// if there is not size bytes after the rover, reset to the start + wrapped_this_time = false; + + if ( !sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size) + { + if (sc_rover) + { + wrapped_this_time = true; + } + sc_rover = sc_base; + } + +// colect and free surfcache_t blocks until the rover block is large enough + new = sc_rover; + if (sc_rover->owner) + *sc_rover->owner = NULL; + + while (new->size < size) + { + // free another + sc_rover = sc_rover->next; + if (!sc_rover) + gEngfuncs.Host_Error ("D_SCAlloc: hit the end of memory"); + if (sc_rover->owner) + *sc_rover->owner = NULL; + + new->size += sc_rover->size; + new->next = sc_rover->next; + } + +// create a fragment out of any leftovers + if (new->size - size > 256) + { + sc_rover = (surfcache_t *)( (byte *)new + size); + sc_rover->size = new->size - size; + sc_rover->next = new->next; + sc_rover->width = 0; + sc_rover->owner = NULL; + new->next = sc_rover; + new->size = size; + } + else + sc_rover = new->next; + + new->width = width; +// DEBUG + if (width > 0) + new->height = (size - sizeof(*new) + sizeof(new->data)) / width; + + new->owner = NULL; // should be set properly after return + + if (d_roverwrapped) + { + if (wrapped_this_time || (sc_rover >= d_initial_rover)) + r_cache_thrash = true; + } + else if (wrapped_this_time) + { + d_roverwrapped = true; + } + + return new; +} + + +/* +================= +D_SCDump +================= +*/ +void D_SCDump (void) +{ + surfcache_t *test; + + for (test = sc_base ; test ; test = test->next) + { + if (test == sc_rover) + gEngfuncs.Con_Printf ("ROVER:\n"); + gEngfuncs.Con_Printf ("%p : %i bytes %i width\n",test, test->size, test->width); + } +} + +//============================================================================= + +// if the num is not a power of 2, assume it will not repeat + +int MaskForNum (int num) +{ + if (num==128) + return 127; + if (num==64) + return 63; + if (num==32) + return 31; + if (num==16) + return 15; + return 255; +} + +int D_log2 (int num) +{ + int c; + + c = 0; + + while (num>>=1) + c++; + return c; +} + +//============================================================================= + +/* +================ +D_CacheSurface +================ +*/ +surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) +{ + surfcache_t *cache; + +// +// if the surface is animating or flashing, flush the cache +// + r_drawsurf.image = R_GetTexture(R_TextureAnimation (surface->texinfo->texture->gl_texturenum)); + + /// todo: port this + //r_drawsurf.lightadj[0] = r_newrefdef.lightstyles[surface->styles[0]].white*128; + //r_drawsurf.lightadj[1] = r_newrefdef.lightstyles[surface->styles[1]].white*128; + //r_drawsurf.lightadj[2] = r_newrefdef.lightstyles[surface->styles[2]].white*128; + //r_drawsurf.lightadj[3] = r_newrefdef.lightstyles[surface->styles[3]].white*128; + +// +// see if the cache holds apropriate data +// + cache = CACHESPOT(surface)[miplevel]; + + + if (cache && !cache->dlight && surface->dlightframe != r_framecount + && cache->image == r_drawsurf.image + && cache->lightadj[0] == r_drawsurf.lightadj[0] + && cache->lightadj[1] == r_drawsurf.lightadj[1] + && cache->lightadj[2] == r_drawsurf.lightadj[2] + && cache->lightadj[3] == r_drawsurf.lightadj[3] ) + return cache; + +// +// determine shape of surface +// + surfscale = 1.0 / (1<extents[0] >> miplevel; + r_drawsurf.rowbytes = r_drawsurf.surfwidth; + r_drawsurf.surfheight = surface->extents[1] >> miplevel; + +// +// allocate memory if needed +// + if (!cache) // if a texture just animated, don't reallocate it + { + cache = D_SCAlloc (r_drawsurf.surfwidth, + r_drawsurf.surfwidth * r_drawsurf.surfheight); + CACHESPOT(surface)[miplevel] = cache; + cache->owner = &CACHESPOT(surface)[miplevel]; + cache->mipscale = surfscale; + } + + if (surface->dlightframe == r_framecount) + cache->dlight = 1; + else + cache->dlight = 0; + + r_drawsurf.surfdat = (pixel_t *)cache->data; + + cache->image = r_drawsurf.image; + cache->lightadj[0] = r_drawsurf.lightadj[0]; + cache->lightadj[1] = r_drawsurf.lightadj[1]; + cache->lightadj[2] = r_drawsurf.lightadj[2]; + cache->lightadj[3] = r_drawsurf.lightadj[3]; + +// +// draw and light the surface texture +// + r_drawsurf.surf = surface; + + c_surf++; + + // calculate the lightings + //R_BuildLightMap (); + + // rasterize the surface into the cache + R_DrawSurface (); + + return cache; +} + + From e7785c9ccb4c39ec8d8758f8431bff90f085e95b Mon Sep 17 00:00:00 2001 From: mittorn Date: Fri, 22 Mar 2019 23:40:27 +0700 Subject: [PATCH 007/115] ref_soft: Make it draw something, screen settings still wrong --- r_edge.c | 30 +++++++++---- r_glblit.c | 3 ++ r_local.h | 6 +-- r_main.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++- r_misc.c | 44 +++++++++++-------- r_rast.c | 28 +++++++++--- r_scan.c | 12 +++--- r_surf.c | 43 ++++++++++--------- 8 files changed, 228 insertions(+), 62 deletions(-) diff --git a/r_edge.c b/r_edge.c index ff3984cb..d2267ca3 100644 --- a/r_edge.c +++ b/r_edge.c @@ -69,6 +69,7 @@ static void (*pdrawfunc)(void); edge_t edge_head; edge_t edge_tail; + edge_t edge_aftertail; edge_t edge_sentinel; @@ -160,9 +161,15 @@ void R_InsertNewEdges (edge_t *edgestoadd, edge_t *edgelist) { next_edge = edgestoadd->next; edgesearch: + if( !edgelist ) + { + // gEngfuncs.Con_Printf("NULL edgelist!\n"); + //return; + } if (edgelist->u >= edgestoadd->u) goto addedge; edgelist=edgelist->next; +#if 1 if (edgelist->u >= edgestoadd->u) goto addedge; edgelist=edgelist->next; @@ -172,6 +179,7 @@ edgesearch: if (edgelist->u >= edgestoadd->u) goto addedge; edgelist=edgelist->next; +#endif goto edgesearch; // insert edgestoadd before edgelist @@ -255,10 +263,14 @@ pushback: // find out where the edge goes in the edge list pwedge = pedge->prev->prev; + // if( !pwedge ) + // return; while (pwedge->u > pedge->u) { pwedge = pwedge->prev; + //if( !pwedge ) + //return; } // put the edge back into the edge list @@ -647,7 +659,7 @@ void R_ScanEdges (void) // clear active edges to just the background edges around the whole screen // FIXME: most of this only needs to be set up once - edge_head.u = 0; //r_refdef.vrect.x << 20; + edge_head.u = 1 << 20; //r_refdef.vrect.x << 20; edge_head_u_shift20 = edge_head.u >> 20; edge_head.u_step = 0; edge_head.prev = NULL; @@ -655,7 +667,7 @@ void R_ScanEdges (void) edge_head.surfs[0] = 0; edge_head.surfs[1] = 1; - edge_tail.u = 0xFFFFF; // (r_refdef.vrectright << 20) + 0xFFFFF; + edge_tail.u =(gpGlobals->width << 20) + 0xFFFFF; // (r_refdef.vrectright << 20) + 0xFFFFF; edge_tail_u_shift20 = edge_tail.u >> 20; edge_tail.u_step = 0; edge_tail.prev = &edge_head; @@ -689,7 +701,7 @@ void R_ScanEdges (void) { R_InsertNewEdges (newedges[iv], edge_head.next); } - +#if 1 (*pdrawfunc) (); // flush the span list if we can't be sure we have enough spans left for @@ -704,7 +716,7 @@ void R_ScanEdges (void) span_p = basespan_p; } - +#endif if (removeedges[iv]) R_RemoveEdges (removeedges[iv]); @@ -779,12 +791,12 @@ Simple single color fill with no texture mapping void D_FlatFillSurface (surf_t *surf, int color) { espan_t *span; - byte *pdest; + pixel_t *pdest; int u, u2; for (span=surf->spans ; span ; span=span->pnext) { - pdest = (byte *)d_viewbuffer + r_screenwidth*span->v; + pdest = d_viewbuffer + r_screenwidth*span->v; u = span->u; u2 = span->u + span->count - 1; for ( ; u <= u2 ; u++) @@ -869,7 +881,7 @@ void D_BackgroundSurf (surf_t *s) d_zistepv = 0; d_ziorigin = -0.9; - D_FlatFillSurface (s, (int)sw_clearcolor->value & 0xFF); + D_FlatFillSurface (s, (int)sw_clearcolor->value & 0xFFFF); D_DrawZSpans (s->spans); } @@ -1027,6 +1039,8 @@ void D_SolidSurf (surf_t *s) } #endif + if( !pface ) + return; // FIXME: make this passed in to D_CacheSurface pcurrentcache = D_CacheSurface (pface, miplevel); @@ -1078,7 +1092,7 @@ void D_DrawflatSurfaces (void) // make a stable color for each surface by taking the low // bits of the msurface pointer - D_FlatFillSurface (s, (int)s->msurf & 0xFF); + D_FlatFillSurface (s, (int)s->msurf & 0xFFFF); D_DrawZSpans (s->spans); } } diff --git a/r_glblit.c b/r_glblit.c index fac3ba30..636fd640 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -168,6 +168,9 @@ void R_InitBlit() R_BuildScreenMap(); R_BuildBlendMaps(); + d_pzbuffer = malloc(vid.width*vid.height*2); + R_InitCaches(); + } void R_BlitScreen() diff --git a/r_local.h b/r_local.h index 8d0eaad0..ed56f0d5 100644 --- a/r_local.h +++ b/r_local.h @@ -783,11 +783,11 @@ extern cvar_t *r_showhull; #define DS_SPAN_LIST_END -128 -#define NUMSTACKEDGES 2000 +#define NUMSTACKEDGES 4000 #define MINEDGES NUMSTACKEDGES -#define NUMSTACKSURFACES 1000 +#define NUMSTACKSURFACES 2000 #define MINSURFACES NUMSTACKSURFACES -#define MAXSPANS 3000 +#define MAXSPANS 6000 // flags in finalvert_t.flags #define ALIAS_LEFT_CLIP 0x0001 diff --git a/r_main.c b/r_main.c index 089ba850..7cfc8517 100644 --- a/r_main.c +++ b/r_main.c @@ -19,6 +19,7 @@ GNU General Public License for more details. //#include "beamdef.h" //#include "particledef.h" #include "entity_types.h" +#include "mod_local.h" #define IsLiquidContents( cnt ) ( cnt == CONTENTS_WATER || cnt == CONTENTS_SLIME || cnt == CONTENTS_LAVA ) @@ -1230,6 +1231,125 @@ void R_EdgeDrawing (void) R_ScanEdges (); } +#if 0 +/* +=============== +R_MarkLeaves + +Mark the leaves and nodes that are in the PVS for the current leaf +=============== +*/ +void R_MarkLeaves( void ) +{ + qboolean novis = false; + qboolean force = false; + mleaf_t *leaf = NULL; + mnode_t *node; + vec3_t test; + int i; + + if( !RI.drawWorld ) return; + + /*if( FBitSet( r_novis->flags, FCVAR_CHANGED ) || tr.fResetVis ) + { + // force recalc viewleaf + ClearBits( r_novis->flags, FCVAR_CHANGED ); + tr.fResetVis = false; + RI.viewleaf = NULL; + }*/ + + VectorCopy( RI.pvsorigin, test ); + + if( RI.viewleaf != NULL ) + { + // merge two leafs that can be a crossed-line contents + if( RI.viewleaf->contents == CONTENTS_EMPTY ) + { + VectorSet( test, RI.pvsorigin[0], RI.pvsorigin[1], RI.pvsorigin[2] - 16.0f ); + leaf = gEngfuncs.Mod_PointInLeaf( test, WORLDMODEL->nodes ); + } + else + { + VectorSet( test, RI.pvsorigin[0], RI.pvsorigin[1], RI.pvsorigin[2] + 16.0f ); + leaf = gEngfuncs.Mod_PointInLeaf( test, WORLDMODEL->nodes ); + } + + if(( leaf->contents != CONTENTS_SOLID ) && ( RI.viewleaf != leaf )) + force = true; + } + + if( RI.viewleaf == RI.oldviewleaf && RI.viewleaf != NULL && !force ) + return; + + // development aid to let you run around + // and see exactly where the pvs ends + //if( sw_lockpvs->value ) return; + + RI.oldviewleaf = RI.viewleaf; + tr.visframecount++; + + if( RI.drawOrtho || !RI.viewleaf || !WORLDMODEL->visdata ) + novis = true; + + gEngfuncs.R_FatPVS( RI.pvsorigin, REFPVS_RADIUS, RI.visbytes, FBitSet( RI.params, RP_OLDVIEWLEAF ), novis ); + if( force && !novis ) gEngfuncs.R_FatPVS( test, REFPVS_RADIUS, RI.visbytes, true, novis ); + + for( i = 0; i < WORLDMODEL->numleafs; i++ ) + { + if( CHECKVISBIT( RI.visbytes, i )) + { + node = (mnode_t *)&WORLDMODEL->leafs[i+1]; + do + { + if( node->visframe == tr.visframecount ) + break; + node->visframe = tr.visframecount; + node = node->parent; + } while( node ); + } + } +} +#else +/* +=============== +R_MarkLeaves +=============== +*/ +void R_MarkLeaves (void) +{ + byte *vis; + mnode_t *node; + int i; + + if (r_oldviewcluster == r_viewcluster && !r_novis->value && r_viewcluster != -1) + return; + + r_visframecount++; + r_oldviewcluster = r_viewcluster; + + gEngfuncs.R_FatPVS( RI.pvsorigin, REFPVS_RADIUS, RI.visbytes, FBitSet( RI.params, RP_OLDVIEWLEAF ), false ); + vis = RI.visbytes; + + for (i = 0; i < WORLDMODEL->numleafs; i++) + { + if (vis[i>>3] & (1<<(i&7))) + { + node = (mnode_t *) &WORLDMODEL->leafs[i+1]; + do + { + if (node->visframe == r_visframecount) + break; + node->visframe = r_visframecount; + node = node->parent; + } while (node); + } + } +} + + + +#endif + /* ================ R_RenderScene @@ -1257,7 +1377,7 @@ void R_RenderScene( void ) // R_SetupGL( true ); R_Clear( ~0 ); - //R_MarkLeaves(); + R_MarkLeaves(); R_DrawFog (); // R_PushDlights (r_worldmodel); ?? R_CheckGLFog(); @@ -1542,7 +1662,7 @@ qboolean R_Init() //r_dspeeds = ri.Cvar_Get ("r_dspeeds", "0", 0); // r_lightlevel = ri.Cvar_Get ("r_lightlevel", "0", 0); //r_lerpmodels = ri.Cvar_Get( "r_lerpmodels", "1", 0 ); - //r_novis = ri.Cvar_Get( "r_novis", "0", 0 ); + r_novis = gEngfuncs.Cvar_Get( "r_novis", "0", 0, "" ); // create the window and set up the context r_temppool = Mem_AllocPool( "ref_sw zone" ); diff --git a/r_misc.c b/r_misc.c index 6ba955ac..b41490c5 100644 --- a/r_misc.c +++ b/r_misc.c @@ -254,55 +254,65 @@ void R_ViewChanged (vrect_t *vr) xOrigin = r_refdef.xOrigin; yOrigin = r_refdef.yOrigin; - + #endif + + int fov_x = 2.0 * tan (RI.fov_x/360*M_PI); + int fov_y = 2.0 * tan (RI.fov_y/360*M_PI); // values for perspective projection // if math were exact, the values would range from 0.5 to to range+0.5 // hopefully they wll be in the 0.000001 to range+.999999 and truncate // the polygon rasterization will never render in the first row or column // but will definately render in the [range] row and column, so adjust the // buffer origin to get an exact edge to edge fill - xcenter = ((float)r_refdef.vrect.width * XCENTERING) + - r_refdef.vrect.x - 0.5; - aliasxcenter = xcenter * r_aliasuvscale; - ycenter = ((float)r_refdef.vrect.height * YCENTERING) + - r_refdef.vrect.y - 0.5; - aliasycenter = ycenter * r_aliasuvscale; - - xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView; - aliasxscale = xscale * r_aliasuvscale; + xcenter = ((float)gpGlobals->width * XCENTERING) + + 0 - 0.5; + //aliasxcenter = xcenter * r_aliasuvscale; + ycenter = ((float)gpGlobals->height * YCENTERING) + + 0 - 0.5; + //aliasycenter = ycenter * r_aliasuvscale; + + xscale = gpGlobals->width * 1.5 / fov_x; + //aliasxscale = xscale * r_aliasuvscale; xscaleinv = 1.0 / xscale; yscale = xscale; - aliasyscale = yscale * r_aliasuvscale; + //aliasyscale = yscale * r_aliasuvscale; yscaleinv = 1.0 / yscale; - xscaleshrink = (r_refdef.vrect.width-6)/r_refdef.horizontalFieldOfView; + xscaleshrink = (gpGlobals->width-6)/fov_x; yscaleshrink = xscaleshrink; + // ??? +#define PLANE_ANYZ 5 + + + int xOrigin = r_origin[0]; + int yOrigin = r_origin[1]; + // left side clip - screenedge[0].normal[0] = -1.0 / (xOrigin*r_refdef.horizontalFieldOfView); + screenedge[0].normal[0] = -1.0 / (xOrigin*fov_x); screenedge[0].normal[1] = 0; screenedge[0].normal[2] = 1; screenedge[0].type = PLANE_ANYZ; // right side clip screenedge[1].normal[0] = - 1.0 / ((1.0-xOrigin)*r_refdef.horizontalFieldOfView); + 1.0 / ((1.0-xOrigin)*fov_x); screenedge[1].normal[1] = 0; screenedge[1].normal[2] = 1; screenedge[1].type = PLANE_ANYZ; // top side clip screenedge[2].normal[0] = 0; - screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView); + screenedge[2].normal[1] = -1.0 / (yOrigin*fov_y); screenedge[2].normal[2] = 1; screenedge[2].type = PLANE_ANYZ; // bottom side clip screenedge[3].normal[0] = 0; - screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView); + screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*fov_y); screenedge[3].normal[2] = 1; screenedge[3].type = PLANE_ANYZ; -#endif + for (i=0 ; i<4 ; i++) VectorNormalize (screenedge[i].normal); diff --git a/r_rast.c b/r_rast.c index 19666843..d9212dcb 100644 --- a/r_rast.c +++ b/r_rast.c @@ -226,6 +226,8 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) int v, v2, ceilv0; float scale, lzi0, u0, v0; int side; + if( isnan( pv0->position[1]) ) + return; if (r_lastvertvalid) { @@ -263,6 +265,13 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) v0 = gpGlobals->height; ceilv0 = (int) ceil(v0); + + if( ceilv0 < 0 ) + { + printf("ceilv0 %d %f %f %f %f\n", ceilv0, v0, scale, transformed[1], ycenter ); + printf("%f %f %f %f\n", world[1],modelorg[1], local[1], transformed[1] ); + + } } world = &pv1->position[0]; @@ -306,7 +315,7 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) // create the edge - if (ceilv0 == r_ceilv1) + if (ceilv0 == r_ceilv1 || ceilv0 < 0 ) { // we cache unclipped horizontal edges as fully clipped if (cacheoffset != 0x7FFFFFFF) @@ -330,6 +339,7 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) { // trailing edge (go from p1 to p2) v = ceilv0; + if( v < 0 )printf("v0 %d\n", v); v2 = r_ceilv1 - 1; edge->surfs[0] = surface_p - surfaces; @@ -343,6 +353,7 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) // leading edge (go from p2 to p1) v2 = ceilv0 - 1; v = r_ceilv1; + if( v < 0 )printf("v1 %d\n", v); edge->surfs[0] = 0; edge->surfs[1] = surface_p - surfaces; @@ -359,10 +370,12 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) // it to incorrectly extend to the scan, and the extension of the line goes off // the edge of the screen // FIXME: is this actually needed? -// if (edge->u < r_refdef.vrect_x_adj_shift20) -// edge->u = r_refdef.vrect_x_adj_shift20; -// if (edge->u > r_refdef.vrectright_adj_shift20) -// edge->u = r_refdef.vrectright_adj_shift20; + int r = (gpGlobals->width<<20) + (1<<19) - 1; + int x = (1<<20) + (1<<19) - 1; + if (edge->u < x) + edge->u = x; + if (edge->u > r) + edge->u = r; // // sort the edge in normally @@ -371,6 +384,11 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) if (edge->surfs[0]) u_check++; // sort trailers after leaders + if( v < 0 ) + { + printf("v %d\n", v); + v = 0; + } if (!newedges[v] || newedges[v]->u >= u_check) { edge->next = newedges[v]; diff --git a/r_scan.c b/r_scan.c index 5aaece7f..f0361371 100644 --- a/r_scan.c +++ b/r_scan.c @@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "r_local.h" -unsigned char *r_turb_pbase, *r_turb_pdest; +pixel_t *r_turb_pbase, *r_turb_pdest; fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep; int *r_turb_turb; int r_turb_spancount; @@ -143,7 +143,7 @@ void Turbulent8 (espan_t *pspan) do { - r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer + + r_turb_pdest = (d_viewbuffer + (r_screenwidth * pspan->v) + pspan->u); count = pspan->count; @@ -271,7 +271,7 @@ void NonTurbulent8 (espan_t *pspan) r_turb_sstep = 0; // keep compiler happy r_turb_tstep = 0; // ditto - r_turb_pbase = (unsigned char *)cacheblock; + r_turb_pbase = cacheblock; sdivz16stepu = d_sdivzstepu * 16; tdivz16stepu = d_tdivzstepu * 16; @@ -279,7 +279,7 @@ void NonTurbulent8 (espan_t *pspan) do { - r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer + + r_turb_pdest = (d_viewbuffer + (r_screenwidth * pspan->v) + pspan->u); count = pspan->count; @@ -401,7 +401,7 @@ D_DrawSpans16 void D_DrawSpans16 (espan_t *pspan) { int count, spancount; - unsigned char *pbase, *pdest; + pixel_t *pbase, *pdest; fixed16_t s, t, snext, tnext, sstep, tstep; float sdivz, tdivz, zi, z, du, dv, spancountminus1; float sdivz8stepu, tdivz8stepu, zi8stepu; @@ -417,7 +417,7 @@ void D_DrawSpans16 (espan_t *pspan) do { - pdest = (unsigned char *)((byte *)d_viewbuffer + + pdest = (d_viewbuffer + (r_screenwidth * pspan->v) + pspan->u); count = pspan->count; diff --git a/r_surf.c b/r_surf.c index cb17b9d1..806e5192 100644 --- a/r_surf.c +++ b/r_surf.c @@ -28,13 +28,13 @@ int lightdelta, lightdeltastep; int lightright, lightleftstep, lightrightstep, blockdivshift; unsigned blockdivmask; void *prowdestbase; -unsigned char *pbasesource; +pixel_t *pbasesource; int surfrowbytes; // used by ASM files unsigned *r_lightptr; int r_stepback; int r_lightwidth; int r_numhblocks, r_numvblocks; -unsigned char *r_source, *r_sourcemax; +pixel_t *r_source, *r_sourcemax; void R_DrawSurfaceBlock8_mip0 (void); void R_DrawSurfaceBlock8_mip1 (void); @@ -188,18 +188,19 @@ R_DrawSurface */ void R_DrawSurface (void) { - unsigned char *basetptr; + pixel_t *basetptr; int smax, tmax, twidth; int u; int soffset, basetoffset, texwidth; int horzblockstep; - unsigned char *pcolumndest; + pixel_t *pcolumndest; void (*pblockdrawer)(void); image_t *mt; surfrowbytes = r_drawsurf.rowbytes; mt = r_drawsurf.image; + r_drawsurf.surfmip = 0; r_source = mt->pixels[r_drawsurf.surfmip]; @@ -219,7 +220,7 @@ void R_DrawSurface (void) //============================== - pblockdrawer = surfmiptable[r_drawsurf.surfmip]; + pblockdrawer = surfmiptable[0]; // TODO: only needs to be set when there is a display settings change horzblockstep = blocksize; @@ -272,7 +273,7 @@ R_DrawSurfaceBlock8_mip0 void R_DrawSurfaceBlock8_mip0 (void) { int v, i, b, lightstep, lighttemp, light; - unsigned char pix, *psource, *prowdest; + pixel_t pix, *psource, *prowdest; psource = pbasesource; prowdest = prowdestbase; @@ -281,11 +282,11 @@ void R_DrawSurfaceBlock8_mip0 (void) { // FIXME: make these locals? // FIXME: use delta rather than both right and left, like ASM? - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 4; - lightrightstep = (r_lightptr[1] - lightright) >> 4; + //lightleft = r_lightptr[0]; + //lightright = r_lightptr[1]; + //r_lightptr += r_lightwidth; + //lightleftstep = (r_lightptr[0] - lightleft) >> 4; + //lightrightstep = (r_lightptr[1] - lightright) >> 4; for (i=0 ; i<16 ; i++) { @@ -297,14 +298,15 @@ void R_DrawSurfaceBlock8_mip0 (void) for (b=15; b>=0; b--) { pix = psource[b]; - prowdest[b] = ((unsigned char *)vid.colormap) - [(light & 0xFF00) + pix]; + prowdest[b] = pix; + //((unsigned char *)vid.colormap) + //[(light & 0xFF00) + pix]; light += lightstep; } psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; + //lightright += lightrightstep; + //lightleft += lightleftstep; prowdest += surfrowbytes; } @@ -489,7 +491,7 @@ void R_InitCaches (void) { size = SURFCACHE_SIZE_AT_320X240; - pix = vid.width*vid.height; + pix =1920 * 1080 * 16; if (pix > 64000) size += (pix-64000)*3; } @@ -543,10 +545,10 @@ surfcache_t *D_SCAlloc (int width, int size) surfcache_t *new; qboolean wrapped_this_time; - if ((width < 0) || (width > 256)) + if ((width < 0) )// || (width > 256)) gEngfuncs.Host_Error ("D_SCAlloc: bad cache width %d\n", width); - if ((size <= 0) || (size > 0x10000)) + if ((size <= 0) || (size > 0x10000000)) gEngfuncs.Host_Error ("D_SCAlloc: bad cache size %d\n", size); size = (int)&((surfcache_t *)0)->data[size]; @@ -674,11 +676,10 @@ D_CacheSurface surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) { surfcache_t *cache; - // // if the surface is animating or flashing, flush the cache // - r_drawsurf.image = R_GetTexture(R_TextureAnimation (surface->texinfo->texture->gl_texturenum)); + r_drawsurf.image = R_GetTexture(R_TextureAnimation (surface)->gl_texturenum); /// todo: port this //r_drawsurf.lightadj[0] = r_newrefdef.lightstyles[surface->styles[0]].white*128; @@ -715,7 +716,7 @@ surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) if (!cache) // if a texture just animated, don't reallocate it { cache = D_SCAlloc (r_drawsurf.surfwidth, - r_drawsurf.surfwidth * r_drawsurf.surfheight); + r_drawsurf.surfwidth * r_drawsurf.surfheight * 2); CACHESPOT(surface)[miplevel] = cache; cache->owner = &CACHESPOT(surface)[miplevel]; cache->mipscale = surfscale; From 842a15ee45fedaf5ebe106707b4d83d710232941 Mon Sep 17 00:00:00 2001 From: mittorn Date: Fri, 22 Mar 2019 23:58:43 +0700 Subject: [PATCH 008/115] ref_soft: Merge kernel texture filter --- r_local.h | 1 + r_main.c | 3 ++- r_scan.c | 72 ++++++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 61 insertions(+), 15 deletions(-) diff --git a/r_local.h b/r_local.h index ed56f0d5..53b1d5f2 100644 --- a/r_local.h +++ b/r_local.h @@ -1195,6 +1195,7 @@ extern cvar_t *sw_reportedgeout; extern cvar_t *sw_stipplealpha; extern cvar_t *sw_surfcacheoverride; extern cvar_t *sw_waterwarp; +extern cvar_t *sw_texfilt; extern vec3_t modelorg; extern vec3_t r_origin; diff --git a/r_main.c b/r_main.c index 7cfc8517..57e69b61 100644 --- a/r_main.c +++ b/r_main.c @@ -83,6 +83,7 @@ cvar_t *sw_reportsurfout; cvar_t *sw_stipplealpha; cvar_t *sw_surfcacheoverride; cvar_t *sw_waterwarp; +cvar_t *sw_texfilt; cvar_t *r_drawworld; cvar_t *r_drawentities; @@ -1654,7 +1655,7 @@ qboolean R_Init() sw_surfcacheoverride = gEngfuncs.Cvar_Get ("sw_surfcacheoverride", "0", 0, ""); sw_waterwarp = gEngfuncs.Cvar_Get ("sw_waterwarp", "1", 0, ""); sw_mode = gEngfuncs.Cvar_Get( "sw_mode", "0", FCVAR_ARCHIVE, ""); - + sw_texfilt = gEngfuncs.Cvar_Get ("sw_texfilt", "0", 0, "texture dither"); //r_lefthand = ri.Cvar_Get( "hand", "0", FCVAR_USERINFO | FCVAR_ARCHIVE ); // r_speeds = ri.Cvar_Get ("r_speeds", "0", 0); diff --git a/r_scan.c b/r_scan.c index f0361371..5e51b8bc 100644 --- a/r_scan.c +++ b/r_scan.c @@ -391,6 +391,20 @@ void NonTurbulent8 (espan_t *pspan) #if !id386 + +int kernel[2][2][2] = +{ + { + {16384,0}, + {49152,32768} + } + , + { + {32768,49152}, + {0,16384} + } +}; + /* ============= D_DrawSpans16 @@ -481,10 +495,10 @@ void D_DrawSpans16 (espan_t *pspan) } else { - // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so - // can't step off polygon), clamp, calculate s and t steps across - // span by division, biasing steps low so we don't run off the - // texture + // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so + // can't step off polygon), clamp, calculate s and t steps across + // span by division, biasing steps low so we don't run off the + // texture spancountminus1 = (float)(spancount - 1); sdivz += d_sdivzstepu * spancountminus1; tdivz += d_tdivzstepu * spancountminus1; @@ -509,17 +523,47 @@ void D_DrawSpans16 (espan_t *pspan) sstep = (snext - s) / (spancount - 1); tstep = (tnext - t) / (spancount - 1); } - } + } - do - { - *pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth); - s += sstep; - t += tstep; - } while (--spancount > 0); - - s = snext; - t = tnext; + + // Drawing phrase + if (sw_texfilt->value == 0.0f) + { + do + { + *pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth); + s += sstep; + t += tstep; + } while (--spancount > 0); + } + else if (sw_texfilt->value == 1.0f) + { + do + { + int idiths = s; + int iditht = t; + + int X = (pspan->u + spancount) & 1; + int Y = (pspan->v)&1; + + //Using the kernel + idiths += kernel[X][Y][0]; + iditht += kernel[X][Y][1]; + + idiths = idiths >> 16; + idiths = idiths ? idiths -1 : idiths; + + + iditht = iditht >> 16; + iditht = iditht ? iditht -1 : iditht; + + + *pdest++ = *(pbase + idiths + iditht * cachewidth); + s += sstep; + t += tstep; + } while (--spancount > 0); + } + } while (count > 0); From a00256a61c934e630ac51ee003e0265aba82ce0d Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 23 Mar 2019 00:46:57 +0700 Subject: [PATCH 009/115] ref_soft: Update API --- r_context.c | 4 ++-- r_image.c | 2 +- r_light.c | 2 +- r_local.h | 53 +++++++++++++++++++++++++++++++++++++++++++++-------- r_main.c | 8 ++++---- r_rast.c | 2 +- wscript | 5 ++--- 7 files changed, 56 insertions(+), 20 deletions(-) diff --git a/r_context.c b/r_context.c index 48e7b997..65821e7c 100644 --- a/r_context.c +++ b/r_context.c @@ -212,9 +212,9 @@ static int GL_RenderGetParm( int parm, int arg ) return gEngfuncs.Mod_SampleSizeForFace( &WORLDMODEL->surfaces[arg] ); return LM_SAMPLE_SIZE; case PARM_SKY_SPHERE: - return gEngfuncs.CL_GetRenderParm( parm, arg ) && !tr.fCustomSkybox; + return ENGINE_GET_PARM_( parm, arg ) && !tr.fCustomSkybox; default: - return gEngfuncs.CL_GetRenderParm( parm, arg ); + return ENGINE_GET_PARM_( parm, arg ); } return 0; } diff --git a/r_image.c b/r_image.c index 07900cbf..95a5291d 100644 --- a/r_image.c +++ b/r_image.c @@ -374,7 +374,7 @@ byte *GL_ApplyFilter( const byte *source, int width, int height ) byte *out = (byte *)source; int i; - if( gEngfuncs.Host_IsQuakeCompatible() ) + if( ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE ) ) return in; for( i = 0; source && i < width * height; i++, in += 4 ) diff --git a/r_light.c b/r_light.c index 7b3e00cf..08bd4fe3 100644 --- a/r_light.c +++ b/r_light.c @@ -58,7 +58,7 @@ void CL_RunLightStyles( void ) continue; } - if( !gEngfuncs.CL_GetRenderParm( PARAM_GAMEPAUSED, 0 ) && frametime <= 0.1f ) + if( !ENGINE_GET_PARM( PARAM_GAMEPAUSED ) && frametime <= 0.1f ) ls->time += frametime; // evaluate local time flight = (int)Q_floor( ls->time * 10 ); diff --git a/r_local.h b/r_local.h index 53b1d5f2..5d3088fa 100644 --- a/r_local.h +++ b/r_local.h @@ -658,12 +658,8 @@ void TriFogParams( float flDensity, int iFogSkybox ); void TriCullFace( TRICULLSTYLE mode ); -// -// r_blitscreen.c -// -void R_BlitScreen(); -void R_InitBlit(); - +#define ENGINE_GET_PARM_ (*gEngfuncs.EngineGetParm) +#define ENGINE_GET_PARM( parm ) ENGINE_GET_PARM_( (parm), 0 ) extern ref_api_t gEngfuncs; extern ref_globals_t *gpGlobals; @@ -807,8 +803,6 @@ extern cvar_t *r_showhull; #define CLIP_EPSILON 0.001 -#define BACKFACE_EPSILON 0.01 - // !!! if this is changed, it must be changed in asm_draw.h too !!! #define NEAR_CLIP 0.01 @@ -1218,6 +1212,49 @@ extern int r_maxvalidedgeoffset; extern int r_currentkey; extern int r_currentbkey; +// +// r_blitscreen.c +// +void R_InitCaches (void); +void R_BlitScreen(); +void R_InitBlit(); + +// +// r_edge.c +// +void R_SurfacePatch (void); +void R_BeginEdgeFrame (void); +void R_RenderWorld (void); +void R_ScanEdges (void); + + +// +// r_surf.c +// +void D_FlushCaches (void); + +// +// r_draw.c +// +void Draw_Fill (int x, int y, int w, int h, int c); + +// +// r_main.c +// +void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]); + +// +// r_misc.c +// +void R_SetupFrameQ (void); +void R_TransformFrustum (void); +void TransformVector (vec3_t in, vec3_t out); + +// +// r_rast.c +// +void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf); +void R_RenderFace (msurface_t *fa, int clipflags); // diff --git a/r_main.c b/r_main.c index 57e69b61..f6c60140 100644 --- a/r_main.c +++ b/r_main.c @@ -827,7 +827,7 @@ static void R_CheckFog( void ) int i, cnt, count; // quake global fog - if( gEngfuncs.Host_IsQuakeCompatible( )) + if( ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE )) { if( !MOVEVARS->fog_settings ) { @@ -852,12 +852,12 @@ static void R_CheckFog( void ) RI.fogEnabled = false; - if( RI.onlyClientDraw || gEngfuncs.GetWaterLevel() < 3 || !RI.drawWorld || !RI.viewleaf ) + if( RI.onlyClientDraw || ENGINE_GET_PARM( PARM_WATER_LEVEL ) < 3 || !RI.drawWorld || !RI.viewleaf ) { if( RI.cached_waterlevel == 3 ) { // in some cases waterlevel jumps from 3 to 1. Catch it - RI.cached_waterlevel = gEngfuncs.GetWaterLevel(); + RI.cached_waterlevel = ENGINE_GET_PARM( PARM_WATER_LEVEL ); RI.cached_contents = CONTENTS_EMPTY; //if( !RI.fogCustom ) pglDisable( GL_FOG ); } @@ -869,7 +869,7 @@ static void R_CheckFog( void ) cnt = ent->curstate.skin; else cnt = RI.viewleaf->contents; - RI.cached_waterlevel = gEngfuncs.GetWaterLevel(); + RI.cached_waterlevel = ENGINE_GET_PARM( PARM_WATER_LEVEL ); if( !IsLiquidContents( RI.cached_contents ) && IsLiquidContents( cnt )) { diff --git a/r_rast.c b/r_rast.c index d9212dcb..11ebef2d 100644 --- a/r_rast.c +++ b/r_rast.c @@ -562,7 +562,7 @@ void R_RenderFace (msurface_t *fa, int clipflags) // environment box surfaces to be emited /* if ( fa->texinfo->flags & SURF_SKY ) { - R_EmitSkyBox (); + R_EmitSkyBox (); return; }*/ diff --git a/wscript b/wscript index 8bed8fa4..a4e4b2c6 100644 --- a/wscript +++ b/wscript @@ -30,17 +30,16 @@ def build(bld): name = get_subproject_name(bld) bld.env = bld.all_envs[name] - libs = [ 'M' ] + libs = [ 'public', 'M' ] source = bld.path.ant_glob(['*.c']) - source += [ '../engine/common/mathlib.c', '../engine/common/crtlib.c', '../engine/common/matrixlib.c' ] - includes = ['.', '../engine', '../engine/common', '../engine/server', '../engine/client', + '../public', '../common', '../pm_shared' ] From c82eb39d54aa9a15e872b0d242c2f94036282a00 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 23 Mar 2019 00:49:46 +0700 Subject: [PATCH 010/115] ref_soft: Skip sky and transparent surfaces (increase FPS) --- r_rast.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/r_rast.c b/r_rast.c index 11ebef2d..5903e960 100644 --- a/r_rast.c +++ b/r_rast.c @@ -551,20 +551,20 @@ void R_RenderFace (msurface_t *fa, int clipflags) clipplane_t *pclip; // translucent surfaces are not drawn by the edge renderer -/* if (fa->texinfo->flags & (SURF_TRANS33|SURF_TRANS66)) + if (fa->flags & (SURF_DRAWTURB|SURF_TRANSPARENT)) { - fa->nextalphasurface = r_alpha_surfaces; - r_alpha_surfaces = fa; + //fa->nextalphasurface = r_alpha_surfaces; + //r_alpha_surfaces = fa; return; - }*/ + } // sky surfaces encountered in the world will cause the // environment box surfaces to be emited -/* if ( fa->texinfo->flags & SURF_SKY ) + if ( fa->flags & SURF_DRAWSKY ) { - R_EmitSkyBox (); + //R_EmitSkyBox (); return; - }*/ + } // skip out if no more surfs if ((surface_p) >= surf_max) From a2e689aba3c59a224d914aa436f4cb069baa6bc0 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 23 Mar 2019 01:19:15 +0700 Subject: [PATCH 011/115] ref_soft: Fix crash on x86 --- r_local.h | 9 ++++++--- r_main.c | 3 ++- r_rast.c | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/r_local.h b/r_local.h index 5d3088fa..c4c43abf 100644 --- a/r_local.h +++ b/r_local.h @@ -779,11 +779,11 @@ extern cvar_t *r_showhull; #define DS_SPAN_LIST_END -128 -#define NUMSTACKEDGES 4000 +#define NUMSTACKEDGES 2000 #define MINEDGES NUMSTACKEDGES -#define NUMSTACKSURFACES 2000 +#define NUMSTACKSURFACES 1000 #define MINSURFACES NUMSTACKSURFACES -#define MAXSPANS 6000 +#define MAXSPANS 3000 // flags in finalvert_t.flags #define ALIAS_LEFT_CLIP 0x0001 @@ -1256,6 +1256,9 @@ void TransformVector (vec3_t in, vec3_t out); void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf); void R_RenderFace (msurface_t *fa, int clipflags); +#if id386 +#error aaa +#endif // // engine callbacks diff --git a/r_main.c b/r_main.c index f6c60140..13c5437f 100644 --- a/r_main.c +++ b/r_main.c @@ -1216,6 +1216,7 @@ void R_EdgeDrawing (void) surf_max = &surfaces[r_cnumsurfs]; // surface 0 doesn't really exist; it's just a dummy because index 0 // is used to indicate no edge attached to surface + memset(&surfaces[0], 0, sizeof(surf_t)); surfaces--; R_SurfacePatch (); } @@ -1596,7 +1597,7 @@ void R_NewMap (void) if (r_cnumsurfs > NUMSTACKSURFACES) { - surfaces = malloc (r_cnumsurfs * sizeof(surf_t)); + surfaces = Mem_Calloc (r_temppool, r_cnumsurfs * sizeof(surf_t)); surface_p = surfaces; surf_max = &surfaces[r_cnumsurfs]; r_surfsonstack = false; diff --git a/r_rast.c b/r_rast.c index 5903e960..fe2367ec 100644 --- a/r_rast.c +++ b/r_rast.c @@ -726,7 +726,7 @@ void R_RenderFace (msurface_t *fa, int clipflags) surface_p->msurf = fa; surface_p->nearzi = r_nearzi; surface_p->flags = fa->flags; - //surface_p->insubmodel = insubmodel; + surface_p->insubmodel = false; surface_p->spanstate = 0; surface_p->entity = RI.currententity; surface_p->key = r_currentkey++; @@ -847,7 +847,7 @@ void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf) surface_p->msurf = psurf; surface_p->nearzi = r_nearzi; surface_p->flags = psurf->flags; - surface_p->insubmodel = true; + surface_p->insubmodel = false; //true; surface_p->spanstate = 0; surface_p->entity = RI.currententity; surface_p->key = r_currentbkey; From bf0d694c713ad9a4eec3654edb8639aef10dc096 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 23 Mar 2019 02:37:56 +0700 Subject: [PATCH 012/115] ref_soft: mipmap support --- r_edge.c | 2 +- r_image.c | 81 ++++++++++++++++++++++++++++++++++++------------------- r_surf.c | 66 +++++++++++++++++++++++---------------------- 3 files changed, 89 insertions(+), 60 deletions(-) diff --git a/r_edge.c b/r_edge.c index d2267ca3..27566dbb 100644 --- a/r_edge.c +++ b/r_edge.c @@ -1011,7 +1011,7 @@ void D_SolidSurf (surf_t *s) pface = s->msurf; #if 1 - miplevel = 0; //D_MipLevelForScale(s->nearzi * scale_for_mip * pface->texinfo->mipadjust); + miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip ); #else { float dot; diff --git a/r_image.c b/r_image.c index 95a5291d..5ae2e48f 100644 --- a/r_image.c +++ b/r_image.c @@ -509,40 +509,67 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) if( !pic->buffer ) return true; - /// TODO: generate mipmaps + buf = pic->buffer; - if( tex->flags & TF_HAS_ALPHA ) - tex->transparent = true; + int mipCount = 4;//GL_CalcMipmapCount( tex, ( buf != NULL )); - tex->pixels[0] = Mem_Calloc( r_temppool, tex->width * tex->height * sizeof(pixel_t) + 64 ); + // NOTE: only single uncompressed textures can be resamples, no mips, no layers, no sides + if(( tex->depth == 1 ) && ( pic->width != tex->width ) || ( pic->height != tex->height )) + data = GL_ResampleTexture( buf, pic->width, pic->height, tex->width, tex->height, normalMap ); + else data = buf; - for( i = 0; i < tex->width * tex->height; i++ ) - { - unsigned int r, g, b, major, minor; -#if 0 - r = pic->buffer[i * 4 + 0] * MASK(5-1) / 255; - g = pic->buffer[i * 4 + 1] * MASK(6-1) / 255; - b = pic->buffer[i * 4 + 2] * MASK(5-1) / 255; -#else - // seems to look better - r = pic->buffer[i * 4 + 0] * BIT(5) / 256; - g = pic->buffer[i * 4 + 1] * BIT(6) / 256; - b = pic->buffer[i * 4 + 2] * BIT(5) / 256; -#endif - // 565 to 332 - major = (((r >> 2) & MASK(3)) << 5) |( (( (g >> 3) & MASK(3)) << 2 ) )| (((b >> 3) & MASK(2))); + //if( !ImageDXT( pic->type ) && !FBitSet( tex->flags, TF_NOMIPMAP ) && FBitSet( pic->flags, IMAGE_ONEBIT_ALPHA )) + // data = GL_ApplyFilter( data, tex->width, tex->height ); - // save minor GBRGBRGB - minor = MOVE_BIT(r,1,5) | MOVE_BIT(r,0,2) | MOVE_BIT(g,2,7) | MOVE_BIT(g,1,4) | MOVE_BIT(g,0,1) | MOVE_BIT(b,2,6)| MOVE_BIT(b,1,3)|MOVE_BIT(b,0,0); - - tex->pixels[0][i] = major << 8 | (minor & 0xFF); - if( tex->transparent ) + // mips will be auto-generated if desired + for( j = 0; j < mipCount; j++ ) + { + width = Q_max( 1, ( tex->width >> j )); + height = Q_max( 1, ( tex->height >> j )); + texsize = GL_CalcTextureSize( width, height, tex->depth ); + size = GL_CalcImageSize( pic->type, width, height, tex->depth ); + //GL_TextureImageRAW( tex, i, j, width, height, tex->depth, pic->type, data ); + tex->pixels[j] = Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 64 ); + int x, y; + if( tex->flags & TF_HAS_ALPHA ) + tex->transparent = true; + + for(i = 0; i < height * width; i++ ) { - unsigned int alpha = (pic->buffer[i * 4 + 3] * 8 / 256) << (16 - 3); - tex->pixels[0][i] = (tex->pixels[0][i] >> 3) | alpha; + unsigned int r, g, b, major, minor; + #if 0 + r = data[i * 4 + 0] * MASK(5-1) / 255; + g = data[i * 4 + 1] * MASK(6-1) / 255; + b = data[i * 4 + 2] * MASK(5-1) / 255; + #else + // seems to look better + r = data[i * 4 + 0] * BIT(5) / 256; + g = data[i * 4 + 1] * BIT(6) / 256; + b = data[i * 4 + 2] * BIT(5) / 256; + #endif + // 565 to 332 + major = (((r >> 2) & MASK(3)) << 5) |( (( (g >> 3) & MASK(3)) << 2 ) )| (((b >> 3) & MASK(2))); + + // save minor GBRGBRGB + minor = MOVE_BIT(r,1,5) | MOVE_BIT(r,0,2) | MOVE_BIT(g,2,7) | MOVE_BIT(g,1,4) | MOVE_BIT(g,0,1) | MOVE_BIT(b,2,6)| MOVE_BIT(b,1,3)|MOVE_BIT(b,0,0); + + tex->pixels[j][i] = major << 8 | (minor & 0xFF); + if( tex->transparent ) + { + unsigned int alpha = (pic->buffer[i * 4 + 3] * 8 / 256) << (16 - 3); + tex->pixels[j][i] = (tex->pixels[j][i] >> 3) | alpha; + } + } - } + if( mipCount > 1 ) + GL_BuildMipMap( data, width, height, tex->depth, tex->flags ); + + tex->size += texsize; + tex->numMips++; + + //GL_CheckTexImageError( tex ); + } #if 0 diff --git a/r_surf.c b/r_surf.c index 806e5192..5708906a 100644 --- a/r_surf.c +++ b/r_surf.c @@ -200,7 +200,6 @@ void R_DrawSurface (void) surfrowbytes = r_drawsurf.rowbytes; mt = r_drawsurf.image; - r_drawsurf.surfmip = 0; r_source = mt->pixels[r_drawsurf.surfmip]; @@ -220,7 +219,7 @@ void R_DrawSurface (void) //============================== - pblockdrawer = surfmiptable[0]; + pblockdrawer = surfmiptable[r_drawsurf.surfmip]; // TODO: only needs to be set when there is a display settings change horzblockstep = blocksize; @@ -324,7 +323,7 @@ R_DrawSurfaceBlock8_mip1 void R_DrawSurfaceBlock8_mip1 (void) { int v, i, b, lightstep, lighttemp, light; - unsigned char pix, *psource, *prowdest; + pixel_t pix, *psource, *prowdest; psource = pbasesource; prowdest = prowdestbase; @@ -333,11 +332,11 @@ void R_DrawSurfaceBlock8_mip1 (void) { // FIXME: make these locals? // FIXME: use delta rather than both right and left, like ASM? - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 3; - lightrightstep = (r_lightptr[1] - lightright) >> 3; + //lightleft = r_lightptr[0]; + //lightright = r_lightptr[1]; + //r_lightptr += r_lightwidth; + //lightleftstep = (r_lightptr[0] - lightleft) >> 3; + //lightrightstep = (r_lightptr[1] - lightright) >> 3; for (i=0 ; i<8 ; i++) { @@ -349,14 +348,15 @@ void R_DrawSurfaceBlock8_mip1 (void) for (b=7; b>=0; b--) { pix = psource[b]; - prowdest[b] = ((unsigned char *)vid.colormap) - [(light & 0xFF00) + pix]; + prowdest[b] = pix; + //((unsigned char *)vid.colormap) + //[(light & 0xFF00) + pix]; light += lightstep; } psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; + //lightright += lightrightstep; + //lightleft += lightleftstep; prowdest += surfrowbytes; } @@ -374,7 +374,7 @@ R_DrawSurfaceBlock8_mip2 void R_DrawSurfaceBlock8_mip2 (void) { int v, i, b, lightstep, lighttemp, light; - unsigned char pix, *psource, *prowdest; + pixel_t pix, *psource, *prowdest; psource = pbasesource; prowdest = prowdestbase; @@ -383,11 +383,11 @@ void R_DrawSurfaceBlock8_mip2 (void) { // FIXME: make these locals? // FIXME: use delta rather than both right and left, like ASM? - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 2; - lightrightstep = (r_lightptr[1] - lightright) >> 2; + //lightleft = r_lightptr[0]; + //lightright = r_lightptr[1]; + //r_lightptr += r_lightwidth; + //lightleftstep = (r_lightptr[0] - lightleft) >> 2; + //lightrightstep = (r_lightptr[1] - lightright) >> 2; for (i=0 ; i<4 ; i++) { @@ -399,14 +399,15 @@ void R_DrawSurfaceBlock8_mip2 (void) for (b=3; b>=0; b--) { pix = psource[b]; - prowdest[b] = ((unsigned char *)vid.colormap) - [(light & 0xFF00) + pix]; + prowdest[b] = pix; + //((unsigned char *)vid.colormap) + //[(light & 0xFF00) + pix]; light += lightstep; } psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; + //lightright += lightrightstep; + //lightleft += lightleftstep; prowdest += surfrowbytes; } @@ -424,7 +425,7 @@ R_DrawSurfaceBlock8_mip3 void R_DrawSurfaceBlock8_mip3 (void) { int v, i, b, lightstep, lighttemp, light; - unsigned char pix, *psource, *prowdest; + pixel_t pix, *psource, *prowdest; psource = pbasesource; prowdest = prowdestbase; @@ -433,11 +434,11 @@ void R_DrawSurfaceBlock8_mip3 (void) { // FIXME: make these locals? // FIXME: use delta rather than both right and left, like ASM? - lightleft = r_lightptr[0]; - lightright = r_lightptr[1]; - r_lightptr += r_lightwidth; - lightleftstep = (r_lightptr[0] - lightleft) >> 1; - lightrightstep = (r_lightptr[1] - lightright) >> 1; + //lightleft = r_lightptr[0]; + //lightright = r_lightptr[1]; + //r_lightptr += r_lightwidth; + //lightleftstep = (r_lightptr[0] - lightleft) >> 1; + //lightrightstep = (r_lightptr[1] - lightright) >> 1; for (i=0 ; i<2 ; i++) { @@ -449,14 +450,15 @@ void R_DrawSurfaceBlock8_mip3 (void) for (b=1; b>=0; b--) { pix = psource[b]; - prowdest[b] = ((unsigned char *)vid.colormap) - [(light & 0xFF00) + pix]; + prowdest[b] = pix; + //((unsigned char *)vid.colormap) + //[(light & 0xFF00) + pix]; light += lightstep; } psource += sourcetstep; - lightright += lightrightstep; - lightleft += lightleftstep; + //lightright += lightrightstep; + //lightleft += lightleftstep; prowdest += surfrowbytes; } From 932ad73441945fb1dd5b6d67dec02fb9f423a980 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 23 Mar 2019 03:25:57 +0700 Subject: [PATCH 013/115] ref_soft: Add OpenMP for blit and 2d draw --- r_draw.c | 10 ++++++++-- r_glblit.c | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/r_draw.c b/r_draw.c index 05f4d10b..96005f83 100644 --- a/r_draw.c +++ b/r_draw.c @@ -65,7 +65,7 @@ Draw_StretchPicImplementation */ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, int s2, int t2, image_t *pic) { - pixel_t *dest, *source; + pixel_t *source, *dest; unsigned int v, u, sv; unsigned int height; unsigned int f, fstep; @@ -104,8 +104,13 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, dest = vid.buffer + y * vid.rowbytes + x; - for (v=0 ; vpixels[0] + sv*pic->width + s1; { @@ -161,6 +166,7 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, } #endif } + dest += vid.rowbytes; } } diff --git a/r_glblit.c b/r_glblit.c index 636fd640..f3eb4f1d 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -179,6 +179,7 @@ void R_BlitScreen() int i; byte *buf = vid.buffer; + #pragma omp parallel for schedule(static) for( i = 0; i < vid.width * vid.height;i++) { #ifdef SEPARATE_BLIT From 4c73f026b2e037bf131fa612d9bfcc9b1720dedd Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 23 Mar 2019 05:39:45 +0700 Subject: [PATCH 014/115] ref_soft: Fix render setup --- r_edge.c | 10 ++--- r_local.h | 26 +++++++++++- r_main.c | 7 ++++ r_misc.c | 115 +++++++++++++++++++++++++----------------------------- r_rast.c | 57 +++++++++++---------------- r_scan.c | 24 ++++++------ 6 files changed, 125 insertions(+), 114 deletions(-) diff --git a/r_edge.c b/r_edge.c index 27566dbb..e6251b03 100644 --- a/r_edge.c +++ b/r_edge.c @@ -134,7 +134,7 @@ void R_BeginEdgeFrame (void) } // FIXME: set with memset - for (v=0 ; vheight ; v++) + for (v=RI.vrect.y ; vwidth]; + max_span_p = &basespan_p[MAXSPANS - RI.vrect.width]; span_p = basespan_p; // clear active edges to just the background edges around the whole screen // FIXME: most of this only needs to be set up once - edge_head.u = 1 << 20; //r_refdef.vrect.x << 20; + edge_head.u = RI.vrect.x << 20; edge_head_u_shift20 = edge_head.u >> 20; edge_head.u_step = 0; edge_head.prev = NULL; @@ -667,7 +667,7 @@ void R_ScanEdges (void) edge_head.surfs[0] = 0; edge_head.surfs[1] = 1; - edge_tail.u =(gpGlobals->width << 20) + 0xFFFFF; // (r_refdef.vrectright << 20) + 0xFFFFF; + edge_tail.u =(RI.vrectright << 20) + 0xFFFFF; // (r_refdef.vrectright << 20) + 0xFFFFF; edge_tail_u_shift20 = edge_tail.u >> 20; edge_tail.u_step = 0; edge_tail.prev = &edge_head; @@ -687,7 +687,7 @@ void R_ScanEdges (void) // // process all scan lines // - bottom = gpGlobals->height; //r_refdef.vrectbottom - 1; + bottom = RI.vrectbottom - 1; for (iv=0 ; ivwidth - d_pix_max; d_vrectbottom_particle = gpGlobals->height - d_pix_max; @@ -223,98 +223,89 @@ Guaranteed to be called before the first refresh void R_ViewChanged (vrect_t *vr) { int i; -#if 0 - r_refdef.vrect = *vr; - - r_refdef.horizontalFieldOfView = 2*tan((float)r_newrefdef.fov_x/360*M_PI);; - verticalFieldOfView = 2*tan((float)r_newrefdef.fov_y/360*M_PI); - - r_refdef.fvrectx = (float)r_refdef.vrect.x; - r_refdef.fvrectx_adj = (float)r_refdef.vrect.x - 0.5; - r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x<<20) + (1<<19) - 1; - r_refdef.fvrecty = (float)r_refdef.vrect.y; - r_refdef.fvrecty_adj = (float)r_refdef.vrect.y - 0.5; - r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width; - r_refdef.vrectright_adj_shift20 = (r_refdef.vrectright<<20) + (1<<19) - 1; - r_refdef.fvrectright = (float)r_refdef.vrectright; - r_refdef.fvrectright_adj = (float)r_refdef.vrectright - 0.5; - r_refdef.vrectrightedge = (float)r_refdef.vrectright - 0.99; - r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height; - r_refdef.fvrectbottom = (float)r_refdef.vrectbottom; - r_refdef.fvrectbottom_adj = (float)r_refdef.vrectbottom - 0.5; - - r_refdef.aliasvrect.x = (int)(r_refdef.vrect.x * r_aliasuvscale); - r_refdef.aliasvrect.y = (int)(r_refdef.vrect.y * r_aliasuvscale); - r_refdef.aliasvrect.width = (int)(r_refdef.vrect.width * r_aliasuvscale); - r_refdef.aliasvrect.height = (int)(r_refdef.vrect.height * r_aliasuvscale); - r_refdef.aliasvrectright = r_refdef.aliasvrect.x + - r_refdef.aliasvrect.width; - r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y + - r_refdef.aliasvrect.height; - - xOrigin = r_refdef.xOrigin; - yOrigin = r_refdef.yOrigin; - #endif - - int fov_x = 2.0 * tan (RI.fov_x/360*M_PI); - int fov_y = 2.0 * tan (RI.fov_y/360*M_PI); + float verticalFieldOfView, xOrigin, yOrigin; + + RI.vrect = *vr; + + RI.horizontalFieldOfView = 2*tan((float)RI.fov_x/360*M_PI); + verticalFieldOfView = 2*tan((float)RI.fov_y/360*M_PI); + + RI.fvrectx = (float)RI.vrect.x; + RI.fvrectx_adj = (float)RI.vrect.x - 0.5; + RI.vrect_x_adj_shift20 = (RI.vrect.x<<20) + (1<<19) - 1; + RI.fvrecty = (float)RI.vrect.y; + RI.fvrecty_adj = (float)RI.vrect.y - 0.5; + RI.vrectright = RI.vrect.x + RI.vrect.width; + RI.vrectright_adj_shift20 = (RI.vrectright<<20) + (1<<19) - 1; + RI.fvrectright = (float)RI.vrectright; + RI.fvrectright_adj = (float)RI.vrectright - 0.5; + RI.vrectrightedge = (float)RI.vrectright - 0.99; + RI.vrectbottom = RI.vrect.y + RI.vrect.height; + RI.fvrectbottom = (float)RI.vrectbottom; + RI.fvrectbottom_adj = (float)RI.vrectbottom - 0.5; + + //RI.aliasvrect.x = (int)(RI.vrect.x * r_aliasuvscale); + //RI.aliasvrect.y = (int)(RI.vrect.y * r_aliasuvscale); + //RI.aliasvrect.width = (int)(RI.vrect.width * r_aliasuvscale); + //RI.aliasvrect.height = (int)(RI.vrect.height * r_aliasuvscale); + RI.aliasvrectright = RI.aliasvrect.x + + RI.aliasvrect.width; + RI.aliasvrectbottom = RI.aliasvrect.y + + RI.aliasvrect.height; + + xOrigin = RI.xOrigin;// = r_origin[0]; + yOrigin = RI.yOrigin;// = r_origin[1]; +#define PLANE_ANYZ 5 // values for perspective projection // if math were exact, the values would range from 0.5 to to range+0.5 // hopefully they wll be in the 0.000001 to range+.999999 and truncate // the polygon rasterization will never render in the first row or column // but will definately render in the [range] row and column, so adjust the // buffer origin to get an exact edge to edge fill - xcenter = ((float)gpGlobals->width * XCENTERING) + - 0 - 0.5; + xcenter = ((float)RI.vrect.width * XCENTERING) + + RI.vrect.x - 0.5; //aliasxcenter = xcenter * r_aliasuvscale; - ycenter = ((float)gpGlobals->height * YCENTERING) + - 0 - 0.5; - //aliasycenter = ycenter * r_aliasuvscale; + ycenter = ((float)RI.vrect.height * YCENTERING) + + RI.vrect.y - 0.5; +// aliasycenter = ycenter * r_aliasuvscale; - xscale = gpGlobals->width * 1.5 / fov_x; - //aliasxscale = xscale * r_aliasuvscale; + xscale = RI.vrect.width / RI.horizontalFieldOfView; +// aliasxscale = xscale * r_aliasuvscale; xscaleinv = 1.0 / xscale; yscale = xscale; - //aliasyscale = yscale * r_aliasuvscale; +// aliasyscale = yscale * r_aliasuvscale; yscaleinv = 1.0 / yscale; - xscaleshrink = (gpGlobals->width-6)/fov_x; + xscaleshrink = (RI.vrect.width-6)/RI.horizontalFieldOfView; yscaleshrink = xscaleshrink; - // ??? -#define PLANE_ANYZ 5 - - - int xOrigin = r_origin[0]; - int yOrigin = r_origin[1]; - // left side clip - screenedge[0].normal[0] = -1.0 / (xOrigin*fov_x); + screenedge[0].normal[0] = -1.0 / (xOrigin*RI.horizontalFieldOfView); screenedge[0].normal[1] = 0; screenedge[0].normal[2] = 1; screenedge[0].type = PLANE_ANYZ; - + // right side clip screenedge[1].normal[0] = - 1.0 / ((1.0-xOrigin)*fov_x); + 1.0 / ((1.0-xOrigin)*RI.horizontalFieldOfView); screenedge[1].normal[1] = 0; screenedge[1].normal[2] = 1; screenedge[1].type = PLANE_ANYZ; - + // top side clip screenedge[2].normal[0] = 0; - screenedge[2].normal[1] = -1.0 / (yOrigin*fov_y); + screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView); screenedge[2].normal[2] = 1; screenedge[2].type = PLANE_ANYZ; - + // bottom side clip screenedge[3].normal[0] = 0; - screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*fov_y); - screenedge[3].normal[2] = 1; + screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView); + screenedge[3].normal[2] = 1; screenedge[3].type = PLANE_ANYZ; for (i=0 ; i<4 ; i++) - VectorNormalize (screenedge[i].normal); + VectorNormalize (screenedge[i].normal); D_ViewChanged (); } diff --git a/r_rast.c b/r_rast.c index fe2367ec..62ad160f 100644 --- a/r_rast.c +++ b/r_rast.c @@ -226,8 +226,6 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) int v, v2, ceilv0; float scale, lzi0, u0, v0; int side; - if( isnan( pv0->position[1]) ) - return; if (r_lastvertvalid) { @@ -252,26 +250,19 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) // FIXME: build x/yscale into transform? scale = xscale * lzi0; u0 = (xcenter + scale*transformed[0]); - if (u0 < 0) - u0 = 0; - if (u0 > gpGlobals->width) - u0 = gpGlobals->width; + if (u0 < RI.fvrectx_adj) + u0 = RI.fvrectx_adj; + if (u0 > RI.fvrectright_adj) + u0 = RI.fvrectright_adj; scale = yscale * lzi0; v0 = (ycenter - scale*transformed[1]); - if (v0 < 0) - v0 = 0; - if (v0 > gpGlobals->height) - v0 = gpGlobals->height; + if (v0 < RI.fvrecty_adj) + v0 = RI.fvrecty_adj; + if (v0 > RI.fvrectbottom_adj) + v0 = RI.fvrectbottom_adj; ceilv0 = (int) ceil(v0); - - if( ceilv0 < 0 ) - { - printf("ceilv0 %d %f %f %f %f\n", ceilv0, v0, scale, transformed[1], ycenter ); - printf("%f %f %f %f\n", world[1],modelorg[1], local[1], transformed[1] ); - - } } world = &pv1->position[0]; @@ -287,17 +278,17 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) scale = xscale * r_lzi1; r_u1 = (xcenter + scale*transformed[0]); - if (r_u1 < 0) - r_u1 = 0; - if (r_u1 > gpGlobals->width) - r_u1 = gpGlobals->width; + if (r_u1 < RI.fvrectx_adj) + r_u1 = RI.fvrectx_adj; + if (r_u1 > RI.fvrectright_adj) + r_u1 = RI.fvrectright_adj; scale = yscale * r_lzi1; r_v1 = (ycenter - scale*transformed[1]); - if (r_v1 < 0) - r_v1 = 0; - if (r_v1 > gpGlobals->height) - r_v1 = gpGlobals->height; + if (r_v1 < RI.fvrecty_adj) + r_v1 = RI.fvrecty_adj; + if (r_v1 > RI.fvrectbottom_adj) + r_v1 = RI.fvrectbottom_adj; if (r_lzi1 > lzi0) lzi0 = r_lzi1; @@ -339,7 +330,6 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) { // trailing edge (go from p1 to p2) v = ceilv0; - if( v < 0 )printf("v0 %d\n", v); v2 = r_ceilv1 - 1; edge->surfs[0] = surface_p - surfaces; @@ -353,7 +343,6 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) // leading edge (go from p2 to p1) v2 = ceilv0 - 1; v = r_ceilv1; - if( v < 0 )printf("v1 %d\n", v); edge->surfs[0] = 0; edge->surfs[1] = surface_p - surfaces; @@ -370,12 +359,17 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) // it to incorrectly extend to the scan, and the extension of the line goes off // the edge of the screen // FIXME: is this actually needed? - int r = (gpGlobals->width<<20) + (1<<19) - 1; + /*int r = (gpGlobals->width<<20) + (1<<19) - 1; int x = (1<<20) + (1<<19) - 1; if (edge->u < x) edge->u = x; if (edge->u > r) - edge->u = r; + edge->u = r;*/ + if (edge->u < RI.vrect_x_adj_shift20) + edge->u = RI.vrect_x_adj_shift20; + if (edge->u > RI.vrectright_adj_shift20) + edge->u = RI.vrectright_adj_shift20; + // // sort the edge in normally @@ -384,11 +378,6 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) if (edge->surfs[0]) u_check++; // sort trailers after leaders - if( v < 0 ) - { - printf("v %d\n", v); - v = 0; - } if (!newedges[v] || newedges[v]->u >= u_check) { edge->next = newedges[v]; diff --git a/r_scan.c b/r_scan.c index 5e51b8bc..4f078df2 100644 --- a/r_scan.c +++ b/r_scan.c @@ -8,7 +8,7 @@ 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. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -129,7 +129,7 @@ void Turbulent8 (espan_t *pspan) fixed16_t snext, tnext; float sdivz, tdivz, zi, z, du, dv, spancountminus1; float sdivz16stepu, tdivz16stepu, zi16stepu; - + r_turb_turb = sintable + ((int)(gpGlobals->time*SPEED)&(CYCLE-1)); r_turb_sstep = 0; // keep compiler happy @@ -264,7 +264,7 @@ void NonTurbulent8 (espan_t *pspan) fixed16_t snext, tnext; float sdivz, tdivz, zi, z, du, dv, spancountminus1; float sdivz16stepu, tdivz16stepu, zi16stepu; - + // r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1)); r_turb_turb = blanktable; @@ -395,13 +395,13 @@ void NonTurbulent8 (espan_t *pspan) int kernel[2][2][2] = { { - {16384,0}, - {49152,32768} + {16384,0}, + {49152,32768} } , { - {32768,49152}, - {0,16384} + {32768,49152}, + {0,16384} } }; @@ -525,7 +525,7 @@ void D_DrawSpans16 (espan_t *pspan) } } - + // Drawing phrase if (sw_texfilt->value == 0.0f) { @@ -539,7 +539,7 @@ void D_DrawSpans16 (espan_t *pspan) else if (sw_texfilt->value == 1.0f) { do - { + { int idiths = s; int iditht = t; @@ -552,18 +552,18 @@ void D_DrawSpans16 (espan_t *pspan) idiths = idiths >> 16; idiths = idiths ? idiths -1 : idiths; - + iditht = iditht >> 16; iditht = iditht ? iditht -1 : iditht; - + *pdest++ = *(pbase + idiths + iditht * cachewidth); s += sstep; t += tstep; } while (--spancount > 0); } - + } while (count > 0); From 5fc39662ec6ef2823f526066456bc346256407b4 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 23 Mar 2019 05:43:41 +0700 Subject: [PATCH 015/115] ref_soft: Increase limits again, this will fix some HL maps --- r_local.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/r_local.h b/r_local.h index 91ed978c..37d2eac3 100644 --- a/r_local.h +++ b/r_local.h @@ -803,11 +803,11 @@ extern cvar_t *r_showhull; #define DS_SPAN_LIST_END -128 -#define NUMSTACKEDGES 2000 +#define NUMSTACKEDGES 4000 #define MINEDGES NUMSTACKEDGES -#define NUMSTACKSURFACES 1000 +#define NUMSTACKSURFACES 2000 #define MINSURFACES NUMSTACKSURFACES -#define MAXSPANS 3000 +#define MAXSPANS 6000 // flags in finalvert_t.flags #define ALIAS_LEFT_CLIP 0x0001 From 58429bbc79f5cd5c9cf56db27fde47fdfa7170a9 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 23 Mar 2019 13:49:55 +0700 Subject: [PATCH 016/115] ref_soft: submodel drawing --- r_bsp.c | 294 +++++++++++++++++++++++++++++++++++++++++++++++++++++- r_local.h | 3 + r_main.c | 212 ++++++++++++++++++++++++++++++++++----- r_rast.c | 8 +- 4 files changed, 489 insertions(+), 28 deletions(-) diff --git a/r_bsp.c b/r_bsp.c index 4f1c49ef..a27a98b1 100644 --- a/r_bsp.c +++ b/r_bsp.c @@ -143,7 +143,7 @@ void R_RotateBmodel (void) R_TransformFrustum (); } - +#if 1 /* ================ @@ -316,7 +316,297 @@ void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) } } +#else +/* +================ +R_RecursiveClipBPoly +================ +*/ +void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) +{ + bedge_t *psideedges[2], *pnextedge, *ptedge; + int i, side, lastside; + float dist, frac, lastdist; + mplane_t *splitplane, tplane; + mvertex_t *pvert, *plastvert, *ptvert; + mnode_t *pn; + + psideedges[0] = psideedges[1] = NULL; + + makeclippededge = false; + +// transform the BSP plane into model space +// FIXME: cache these? + splitplane = pnode->plane; + tplane.dist = splitplane->dist - + DotProduct(r_entorigin, splitplane->normal); + tplane.normal[0] = DotProduct (entity_rotation[0], splitplane->normal); + tplane.normal[1] = DotProduct (entity_rotation[1], splitplane->normal); + tplane.normal[2] = DotProduct (entity_rotation[2], splitplane->normal); + +// clip edges to BSP plane + for ( ; pedges ; pedges = pnextedge) + { + pnextedge = pedges->pnext; + + // set the status for the last point as the previous point + // FIXME: cache this stuff somehow? + plastvert = pedges->v[0]; + lastdist = DotProduct (plastvert->position, tplane.normal) - + tplane.dist; + + if (lastdist > 0) + lastside = 0; + else + lastside = 1; + + pvert = pedges->v[1]; + + dist = DotProduct (pvert->position, tplane.normal) - tplane.dist; + + if (dist > 0) + side = 0; + else + side = 1; + + if (side != lastside) + { + // clipped + if (numbverts >= MAX_BMODEL_VERTS) + return; + + // generate the clipped vertex + frac = lastdist / (lastdist - dist); + ptvert = &pbverts[numbverts++]; + ptvert->position[0] = plastvert->position[0] + + frac * (pvert->position[0] - + plastvert->position[0]); + ptvert->position[1] = plastvert->position[1] + + frac * (pvert->position[1] - + plastvert->position[1]); + ptvert->position[2] = plastvert->position[2] + + frac * (pvert->position[2] - + plastvert->position[2]); + // split into two edges, one on each side, and remember entering + // and exiting points + // FIXME: share the clip edge by having a winding direction flag? + if (numbedges >= (MAX_BMODEL_EDGES - 1)) + { + gEngfuncs.Con_Printf ("Out of edges for bmodel\n"); + return; + } + + ptedge = &pbedges[numbedges]; + ptedge->pnext = psideedges[lastside]; + psideedges[lastside] = ptedge; + ptedge->v[0] = plastvert; + ptedge->v[1] = ptvert; + + ptedge = &pbedges[numbedges + 1]; + ptedge->pnext = psideedges[side]; + psideedges[side] = ptedge; + ptedge->v[0] = ptvert; + ptedge->v[1] = pvert; + + numbedges += 2; + + if (side == 0) + { + // entering for front, exiting for back + pfrontenter = ptvert; + makeclippededge = true; + } + else + { + pfrontexit = ptvert; + makeclippededge = true; + } + } + else + { + // add the edge to the appropriate side + pedges->pnext = psideedges[side]; + psideedges[side] = pedges; + } + } + +// if anything was clipped, reconstitute and add the edges along the clip +// plane to both sides (but in opposite directions) + if (makeclippededge) + { + if (numbedges >= (MAX_BMODEL_EDGES - 2)) + { + gEngfuncs.Con_Printf ("Out of edges for bmodel\n"); + return; + } + + ptedge = &pbedges[numbedges]; + ptedge->pnext = psideedges[0]; + psideedges[0] = ptedge; + ptedge->v[0] = pfrontexit; + ptedge->v[1] = pfrontenter; + + ptedge = &pbedges[numbedges + 1]; + ptedge->pnext = psideedges[1]; + psideedges[1] = ptedge; + ptedge->v[0] = pfrontenter; + ptedge->v[1] = pfrontexit; + + numbedges += 2; + } + +// draw or recurse further + for (i=0 ; i<2 ; i++) + { + if (psideedges[i]) + { + // draw if we've reached a non-solid leaf, done if all that's left is a + // solid leaf, and continue down the tree if it's not a leaf + pn = pnode->children[i]; + + // we're done with this branch if the node or leaf isn't in the PVS + if (pn->visframe == r_visframecount) + { + if (pn->contents < 0) + { + if (pn->contents != CONTENTS_SOLID) + { + r_currentbkey = ((mleaf_t *)pn)->cluster; + R_RenderBmodelFace (psideedges[i], psurf); + } + } + else + { + R_RecursiveClipBPoly (psideedges[i], pnode->children[i], + psurf); + } + } + } + } +} +#endif +#if 0 +/* +================ +R_DrawSolidClippedSubmodelPolygons +================ +*/ +void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel) +{ + int i, j, lindex; + vec_t dot; + msurface_t *psurf; + int numsurfaces; + mplane_t *pplane; + mvertex_t bverts[MAX_BMODEL_VERTS]; + bedge_t bedges[MAX_BMODEL_EDGES], *pbedge; + medge_t *pedge, *pedges; + +// FIXME: use bounding-box-based frustum clipping info? + + psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; + numsurfaces = pmodel->nummodelsurfaces; + pedges = pmodel->edges; + + for (i=0 ; iplane; + + dot = DotProduct (modelorg, pplane->normal) - pplane->dist; + + // draw the polygon + if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || + (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) + { + // FIXME: use bounding-box-based frustum clipping info? + + // copy the edges to bedges, flipping if necessary so always + // clockwise winding + // FIXME: if edges and vertices get caches, these assignments must move + // outside the loop, and overflow checking must be done here + pbverts = bverts; + pbedges = bedges; + numbverts = numbedges = 0; + + if (psurf->numedges > 0) + { + pbedge = &bedges[numbedges]; + numbedges += psurf->numedges; + + for (j=0 ; jnumedges ; j++) + { + lindex = pmodel->surfedges[psurf->firstedge+j]; + + if (lindex > 0) + { + pedge = &pedges[lindex]; + pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[0]]; + pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[1]]; + } + else + { + lindex = -lindex; + pedge = &pedges[lindex]; + pbedge[j].v[0] = &r_pcurrentvertbase[pedge->v[1]]; + pbedge[j].v[1] = &r_pcurrentvertbase[pedge->v[0]]; + } + + pbedge[j].pnext = &pbedge[j+1]; + } + + pbedge[j-1].pnext = NULL; // mark end of edges + + R_RecursiveClipBPoly (pbedge, RI.currententity->topnode, psurf); + } + else + { + gEngfuncs.Host_Error ("no edges in bmodel"); + } + } + } +} + + +/* +================ +R_DrawSubmodelPolygons +================ +*/ +void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags) +{ + int i; + vec_t dot; + msurface_t *psurf; + int numsurfaces; + mplane_t *pplane; + +// FIXME: use bounding-box-based frustum clipping info? + + psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; + numsurfaces = pmodel->nummodelsurfaces; + + for (i=0 ; iplane; + + dot = DotProduct (modelorg, pplane->normal) - pplane->dist; + + // draw the polygon + if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || + (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) + { + r_currentkey = ((mleaf_t *)RI.currententity->topnode)->cluster; + + // FIXME: use bounding-box-based frustum clipping info? + R_RenderFace (psurf, clipflags); + } + } +} + +#else /* ================ @@ -436,6 +726,8 @@ void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags, mnode_t *topnode) } } +#endif + int c_drawnode; diff --git a/r_local.h b/r_local.h index 37d2eac3..d3e8320e 100644 --- a/r_local.h +++ b/r_local.h @@ -1235,6 +1235,9 @@ extern mvertex_t *r_pcurrentvertbase; extern int r_maxvalidedgeoffset; extern int r_currentkey; extern int r_currentbkey; +extern qboolean insubmodel; + +extern vec3_t r_entorigin; // // r_blitscreen.c diff --git a/r_main.c b/r_main.c index 94b05473..3c3310e0 100644 --- a/r_main.c +++ b/r_main.c @@ -1097,7 +1097,156 @@ void R_DrawEntitiesOnList( void ) //GL_CheckForErrors(); } -#if 0 +#if 1 +qboolean insubmodel; + + +/* +============= +R_BmodelCheckBBox +============= +*/ +int R_BmodelCheckBBox (float *minmaxs) +{ + int i, *pindex, clipflags; + vec3_t acceptpt, rejectpt; + float d; + + clipflags = 0; + + for (i=0 ; i<4 ; i++) + { + // generate accept and reject points + // FIXME: do with fast look-ups or integer tests based on the sign bit + // of the floating point values + + pindex = pfrustum_indexes[i]; + + rejectpt[0] = minmaxs[pindex[0]]; + rejectpt[1] = minmaxs[pindex[1]]; + rejectpt[2] = minmaxs[pindex[2]]; + + d = DotProduct (rejectpt, view_clipplanes[i].normal); + d -= view_clipplanes[i].dist; + + if (d <= 0) + return BMODEL_FULLY_CLIPPED; + + acceptpt[0] = minmaxs[pindex[3+0]]; + acceptpt[1] = minmaxs[pindex[3+1]]; + acceptpt[2] = minmaxs[pindex[3+2]]; + + d = DotProduct (acceptpt, view_clipplanes[i].normal); + d -= view_clipplanes[i].dist; + + if (d <= 0) + clipflags |= (1<nodes; + + while (1) + { + if (node->visframe != r_visframecount) + return NULL; // not visible at all + + if (node->contents < 0) + { + if (node->contents != CONTENTS_SOLID) + return node; // we've reached a non-solid leaf, so it's + // visible and not BSP clipped + return NULL; // in solid, so not visible + } + + splitplane = node->plane; + sides = BOX_ON_PLANE_SIDE (mins, maxs, splitplane); + + if (sides == 3) + return node; // this is the splitter + + // not split yet; recurse down the contacted side + if (sides & 1) + node = node->children[0]; + else + node = node->children[1]; + } +} + + +/* +============= +RotatedBBox + +Returns an axially aligned box that contains the input box at the given rotation +============= +*/ +void RotatedBBox (vec3_t mins, vec3_t maxs, vec3_t angles, vec3_t tmins, vec3_t tmaxs) +{ + vec3_t tmp, v; + int i, j; + vec3_t forward, right, up; + + if (!angles[0] && !angles[1] && !angles[2]) + { + VectorCopy (mins, tmins); + VectorCopy (maxs, tmaxs); + return; + } + + for (i=0 ; i<3 ; i++) + { + tmins[i] = 99999; + tmaxs[i] = -99999; + } + + AngleVectors (angles, forward, right, up); + + for ( i = 0; i < 8; i++ ) + { + if ( i & 1 ) + tmp[0] = mins[0]; + else + tmp[0] = maxs[0]; + + if ( i & 2 ) + tmp[1] = mins[1]; + else + tmp[1] = maxs[1]; + + if ( i & 4 ) + tmp[2] = mins[2]; + else + tmp[2] = maxs[2]; + + + VectorScale (forward, tmp[0], v); + VectorMA (v, -tmp[1], right, v); + VectorMA (v, tmp[2], up, v); + + for (j=0 ; j<3 ; j++) + { + if (v[j] < tmins[j]) + tmins[j] = v[j]; + if (v[j] > tmaxs[j]) + tmaxs[j] = v[j]; + } + } +} + /* ============= @@ -1117,26 +1266,26 @@ void R_DrawBEntitiesOnList (void) VectorCopy (modelorg, oldorigin); insubmodel = true; - r_dlightframecount = r_framecount; + //r_dlightframecount = r_framecount; - for (i=0 ; inum_solid_entities && !RI.onlyClientDraw; i++ ) { - currententity = &r_newrefdef.entities[i]; - currentmodel = currententity->model; - if (!currentmodel) + RI.currententity = tr.draw_list->solid_entities[i]; + RI.currentmodel = RI.currententity->model; + if (!RI.currentmodel) continue; - if (currentmodel->nummodelsurfaces == 0) + if (RI.currentmodel->nummodelsurfaces == 0) continue; // clip brush only - if ( currententity->flags & RF_BEAM ) - continue; - if (currentmodel->type != mod_brush) + //if ( currententity->flags & RF_BEAM ) + //continue; + if (RI.currentmodel->type != mod_brush) continue; // see if the bounding box lets us trivially reject, also sets // trivial accept status - RotatedBBox (currentmodel->mins, currentmodel->maxs, - currententity->angles, mins, maxs); - VectorAdd (mins, currententity->origin, minmaxs); - VectorAdd (maxs, currententity->origin, (minmaxs+3)); + RotatedBBox (RI.currentmodel->mins, RI.currentmodel->maxs, + RI.currententity->angles, mins, maxs); + VectorAdd (mins, RI.currententity->origin, minmaxs); + VectorAdd (maxs, RI.currententity->origin, (minmaxs+3)); clipflags = R_BmodelCheckBBox (minmaxs); if (clipflags == BMODEL_FULLY_CLIPPED) @@ -1146,30 +1295,47 @@ void R_DrawBEntitiesOnList (void) if (!topnode) continue; // no part in a visible leaf - VectorCopy (currententity->origin, r_entorigin); + VectorCopy (RI.currententity->origin, r_entorigin); VectorSubtract (r_origin, r_entorigin, modelorg); - - r_pcurrentvertbase = currentmodel->vertexes; + //VectorSubtract (r_origin, RI.currententity->origin, modelorg); + r_pcurrentvertbase = RI.currentmodel->vertexes; // FIXME: stop transforming twice R_RotateBmodel (); // calculate dynamic lighting for bmodel - R_PushDlights (currentmodel); + // this will reset RI.currententity, do we need this? + //R_PushDlights (); + /*if (clmodel->firstmodelsurface != 0) + { + for (k=0 ; knodes + clmodel->firstnode); + } + }*/ - if (topnode->contents == CONTENTS_NODE) + // RI.currentmodel = tr.draw_list->solid_entities[i]->model; + // RI.currententity = tr.draw_list->solid_entities[i]; + RI.currententity->topnode = topnode; +//ASSERT( RI.currentmodel == tr.draw_list->solid_entities[i]->model ); + if (topnode->contents >= 0) { // not a leaf; has to be clipped to the world BSP r_clipflags = clipflags; - R_DrawSolidClippedSubmodelPolygons (currentmodel, topnode); + R_DrawSolidClippedSubmodelPolygons (RI.currentmodel, topnode); } else { // falls entirely in one leaf, so we just put all the // edges in the edge list and let 1/z sorting handle // drawing order - R_DrawSubmodelPolygons (currentmodel, clipflags, topnode); + //ASSERT( RI.currentmodel == tr.draw_list->solid_entities[i]->model ); + + + R_DrawSubmodelPolygons (RI.currentmodel, clipflags, topnode); } + RI.currententity->topnode = NULL; // put back world rotation and frustum clipping // FIXME: R_RotateBmodel should just work off base_vxx @@ -1227,7 +1393,7 @@ void R_EdgeDrawing (void) R_RenderWorld (); // move brushes to separate list to merge with edges? - //R_DrawBEntitiesOnList (); + R_DrawBEntitiesOnList (); // display all edges R_ScanEdges (); @@ -1372,7 +1538,7 @@ void R_RenderScene( void ) // begin a new frame tr.framecount++; -// R_PushDlights(); + R_PushDlights(); R_SetupFrustum(); R_SetupFrame(); diff --git a/r_rast.c b/r_rast.c index 62ad160f..9b6b2b25 100644 --- a/r_rast.c +++ b/r_rast.c @@ -600,7 +600,7 @@ void R_RenderFace (msurface_t *fa, int clipflags) r_pedge = &pedges[lindex]; // if the edge is cached, we can just reuse the edge - //if (!insubmodel) + if (!insubmodel) { if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) { @@ -644,7 +644,7 @@ void R_RenderFace (msurface_t *fa, int clipflags) lindex = -lindex; r_pedge = &pedges[lindex]; // if the edge is cached, we can just reuse the edge - //if (!insubmodel) + if (!insubmodel) { if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) { @@ -715,7 +715,7 @@ void R_RenderFace (msurface_t *fa, int clipflags) surface_p->msurf = fa; surface_p->nearzi = r_nearzi; surface_p->flags = fa->flags; - surface_p->insubmodel = false; + surface_p->insubmodel = insubmodel; surface_p->spanstate = 0; surface_p->entity = RI.currententity; surface_p->key = r_currentkey++; @@ -836,7 +836,7 @@ void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf) surface_p->msurf = psurf; surface_p->nearzi = r_nearzi; surface_p->flags = psurf->flags; - surface_p->insubmodel = false; //true; + surface_p->insubmodel = true; surface_p->spanstate = 0; surface_p->entity = RI.currententity; surface_p->key = r_currentbkey; From e7f369a765f09d5cbac23f94b5cb6c5662019250 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 23 Mar 2019 14:50:53 +0700 Subject: [PATCH 017/115] ref_soft: Fix breaking server vis, transparent texture decoding --- r_bsp.c | 12 ++++++++---- r_local.h | 3 +++ r_main.c | 21 ++++++++++++++------- r_surf.c | 15 ++++++++++++++- 4 files changed, 39 insertions(+), 12 deletions(-) diff --git a/r_bsp.c b/r_bsp.c index a27a98b1..3478e1cf 100644 --- a/r_bsp.c +++ b/r_bsp.c @@ -143,7 +143,7 @@ void R_RotateBmodel (void) R_TransformFrustum (); } -#if 1 +#if 0 /* ================ @@ -472,7 +472,8 @@ void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) { if (pn->contents != CONTENTS_SOLID) { - r_currentbkey = ((mleaf_t *)pn)->cluster; + //r_currentbkey = ((mleaf_t *)pn)->cluster; + r_currentbkey = LEAF_KEY (((mleaf_t *)pn)); R_RenderBmodelFace (psideedges[i], psurf); } } @@ -718,7 +719,7 @@ void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags, mnode_t *topnode) if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) { - r_currentkey = ((mleaf_t *)topnode)->cluster; + r_currentkey = LEAF_KEY(((mleaf_t *)topnode)); // FIXME: use bounding-box-based frustum clipping info? R_RenderFace (psurf, clipflags); @@ -730,6 +731,7 @@ void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags, mnode_t *topnode) int c_drawnode; +int r_leafkeys[MAX_MAP_LEAFS]; /* ================ @@ -812,7 +814,9 @@ void R_RecursiveWorldNode (mnode_t *node, int clipflags) gEngfuncs.R_StoreEfrags(&pleaf->efrags,tr.realframecount); } - pleaf->cluster = r_currentkey; + + // pleaf->cluster + LEAF_KEY(pleaf) = r_currentkey; r_currentkey++; // all bmodels in a leaf share the same key } else diff --git a/r_local.h b/r_local.h index d3e8320e..4eb47a99 100644 --- a/r_local.h +++ b/r_local.h @@ -1239,6 +1239,9 @@ extern qboolean insubmodel; extern vec3_t r_entorigin; +extern int r_leafkeys[MAX_MAP_LEAFS]; +#define LEAF_KEY(pleaf) r_leafkeys[(pleaf - WORLDMODEL->leafs)] + // // r_blitscreen.c // diff --git a/r_main.c b/r_main.c index 3c3310e0..5521419d 100644 --- a/r_main.c +++ b/r_main.c @@ -398,7 +398,8 @@ qboolean R_AddEntity( struct cl_entity_s *clent, int type ) if( type == ET_FRAGMENTED ) r_stats.c_client_ents++; - if( R_OpaqueEntity( clent )) + // debug: mark all solid + if( true ) // R_OpaqueEntity( clent )) { // opaque if( tr.draw_list->num_solid_entities >= MAX_VISIBLE_PACKET ) @@ -1261,9 +1262,6 @@ void R_DrawBEntitiesOnList (void) float minmaxs[6]; mnode_t *topnode; - if (!r_drawentities->value) - return; - VectorCopy (modelorg, oldorigin); insubmodel = true; //r_dlightframecount = r_framecount; @@ -1284,12 +1282,21 @@ void R_DrawBEntitiesOnList (void) // trivial accept status RotatedBBox (RI.currentmodel->mins, RI.currentmodel->maxs, RI.currententity->angles, mins, maxs); +#if 0 + mins[0] = mins[0] - 100; + mins[1] = mins[1] - 100; + mins[2] = mins[2] - 100; + maxs[0] = maxs[0] + 100; + maxs[1] = maxs[1] + 100; + maxs[2] = maxs[2] + 100; +#endif VectorAdd (mins, RI.currententity->origin, minmaxs); VectorAdd (maxs, RI.currententity->origin, (minmaxs+3)); clipflags = R_BmodelCheckBBox (minmaxs); if (clipflags == BMODEL_FULLY_CLIPPED) continue; // off the edge of the screen + //clipflags = 0; topnode = R_FindTopnode (minmaxs, minmaxs+3); if (!topnode) @@ -1319,13 +1326,13 @@ void R_DrawBEntitiesOnList (void) // RI.currententity = tr.draw_list->solid_entities[i]; RI.currententity->topnode = topnode; //ASSERT( RI.currentmodel == tr.draw_list->solid_entities[i]->model ); - if (topnode->contents >= 0) + //if (topnode->contents >= 0) { // not a leaf; has to be clipped to the world BSP r_clipflags = clipflags; R_DrawSolidClippedSubmodelPolygons (RI.currentmodel, topnode); } - else + //else { // falls entirely in one leaf, so we just put all the // edges in the edge list and let 1/z sorting handle @@ -1333,7 +1340,7 @@ void R_DrawBEntitiesOnList (void) //ASSERT( RI.currentmodel == tr.draw_list->solid_entities[i]->model ); - R_DrawSubmodelPolygons (RI.currentmodel, clipflags, topnode); + //R_DrawSubmodelPolygons (RI.currentmodel, clipflags, topnode); } RI.currententity->topnode = NULL; diff --git a/r_surf.c b/r_surf.c index 5708906a..0a1db660 100644 --- a/r_surf.c +++ b/r_surf.c @@ -180,7 +180,7 @@ texture_t *R_TextureAnimation( msurface_t *s ) return base; } - +static char r_transtexture; /* =============== R_DrawSurface @@ -200,6 +200,7 @@ void R_DrawSurface (void) surfrowbytes = r_drawsurf.rowbytes; mt = r_drawsurf.image; + r_transtexture = mt->transparent; r_source = mt->pixels[r_drawsurf.surfmip]; @@ -276,6 +277,7 @@ void R_DrawSurfaceBlock8_mip0 (void) psource = pbasesource; prowdest = prowdestbase; + char transtexture = r_transtexture; for (v=0 ; v=0; b--) { pix = psource[b]; + if( transtexture ) + pix = pix << 3; prowdest[b] = pix; //((unsigned char *)vid.colormap) //[(light & 0xFF00) + pix]; @@ -324,6 +328,7 @@ void R_DrawSurfaceBlock8_mip1 (void) { int v, i, b, lightstep, lighttemp, light; pixel_t pix, *psource, *prowdest; + char transtexture = r_transtexture; psource = pbasesource; prowdest = prowdestbase; @@ -348,6 +353,8 @@ void R_DrawSurfaceBlock8_mip1 (void) for (b=7; b>=0; b--) { pix = psource[b]; + if( transtexture ) + pix = pix << 3; prowdest[b] = pix; //((unsigned char *)vid.colormap) //[(light & 0xFF00) + pix]; @@ -375,6 +382,7 @@ void R_DrawSurfaceBlock8_mip2 (void) { int v, i, b, lightstep, lighttemp, light; pixel_t pix, *psource, *prowdest; + char transtexture = r_transtexture; psource = pbasesource; prowdest = prowdestbase; @@ -399,6 +407,8 @@ void R_DrawSurfaceBlock8_mip2 (void) for (b=3; b>=0; b--) { pix = psource[b]; + if( transtexture ) + pix = pix << 3; prowdest[b] = pix; //((unsigned char *)vid.colormap) //[(light & 0xFF00) + pix]; @@ -426,6 +436,7 @@ void R_DrawSurfaceBlock8_mip3 (void) { int v, i, b, lightstep, lighttemp, light; pixel_t pix, *psource, *prowdest; + char transtexture = r_transtexture; psource = pbasesource; prowdest = prowdestbase; @@ -450,6 +461,8 @@ void R_DrawSurfaceBlock8_mip3 (void) for (b=1; b>=0; b--) { pix = psource[b]; + if( transtexture ) + pix = pix << 3; prowdest[b] = pix; //((unsigned char *)vid.colormap) //[(light & 0xFF00) + pix]; From e0ce5640d11f5793442f8650ddd05428716ff927 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 23 Mar 2019 18:49:27 +0700 Subject: [PATCH 018/115] ref_soft: Separate buffer for transparent textures --- r_draw.c | 14 ++++++++++++-- r_image.c | 8 ++++---- r_local.h | 3 ++- r_surf.c | 14 -------------- 4 files changed, 18 insertions(+), 21 deletions(-) diff --git a/r_draw.c b/r_draw.c index 96005f83..26f9cbe9 100644 --- a/r_draw.c +++ b/r_draw.c @@ -70,6 +70,8 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, unsigned int height; unsigned int f, fstep; int skip; + qboolean transparent = false; + pixel_t *buffer; if( x < 0 ) { @@ -104,6 +106,14 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, dest = vid.buffer + y * vid.rowbytes + x; + if( pic->alpha_pixels ) + { + buffer = pic->alpha_pixels; + transparent = true; + } + else + buffer = pic->pixels[0]; + #pragma omp parallel for schedule(static) for (v=0 ; vpixels[0] + sv*pic->width + s1; + source = buffer + sv*pic->width + s1; { f = 0; fstep = s2*0x10000/w; @@ -137,7 +147,7 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, int alpha = vid.alpha; f += fstep; - if( pic->transparent ) + if( transparent ) { alpha &= src >> 16 - 3; src = src << 3; diff --git a/r_image.c b/r_image.c index 5ae2e48f..200b4eb7 100644 --- a/r_image.c +++ b/r_image.c @@ -530,9 +530,9 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) size = GL_CalcImageSize( pic->type, width, height, tex->depth ); //GL_TextureImageRAW( tex, i, j, width, height, tex->depth, pic->type, data ); tex->pixels[j] = Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 64 ); + if( j == 0 && tex->flags & TF_HAS_ALPHA ) + tex->alpha_pixels = Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 64 ); int x, y; - if( tex->flags & TF_HAS_ALPHA ) - tex->transparent = true; for(i = 0; i < height * width; i++ ) { @@ -554,10 +554,10 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) minor = MOVE_BIT(r,1,5) | MOVE_BIT(r,0,2) | MOVE_BIT(g,2,7) | MOVE_BIT(g,1,4) | MOVE_BIT(g,0,1) | MOVE_BIT(b,2,6)| MOVE_BIT(b,1,3)|MOVE_BIT(b,0,0); tex->pixels[j][i] = major << 8 | (minor & 0xFF); - if( tex->transparent ) + if( j == 0 && tex->alpha_pixels ) { unsigned int alpha = (pic->buffer[i * 4 + 3] * 8 / 256) << (16 - 3); - tex->pixels[j][i] = (tex->pixels[j][i] >> 3) | alpha; + tex->alpha_pixels[i] = (tex->pixels[j][i] >> 3) | alpha; } } diff --git a/r_local.h b/r_local.h index 4eb47a99..932f3aa7 100644 --- a/r_local.h +++ b/r_local.h @@ -358,8 +358,9 @@ typedef struct image_s float yscale; imagetype_t type; - qboolean transparent; pixel_t *pixels[4]; // mip levels + pixel_t *alpha_pixels; // mip levels + int servercount; uint hashValue; diff --git a/r_surf.c b/r_surf.c index 0a1db660..35503974 100644 --- a/r_surf.c +++ b/r_surf.c @@ -180,7 +180,6 @@ texture_t *R_TextureAnimation( msurface_t *s ) return base; } -static char r_transtexture; /* =============== R_DrawSurface @@ -200,7 +199,6 @@ void R_DrawSurface (void) surfrowbytes = r_drawsurf.rowbytes; mt = r_drawsurf.image; - r_transtexture = mt->transparent; r_source = mt->pixels[r_drawsurf.surfmip]; @@ -277,7 +275,6 @@ void R_DrawSurfaceBlock8_mip0 (void) psource = pbasesource; prowdest = prowdestbase; - char transtexture = r_transtexture; for (v=0 ; v=0; b--) { pix = psource[b]; - if( transtexture ) - pix = pix << 3; prowdest[b] = pix; //((unsigned char *)vid.colormap) //[(light & 0xFF00) + pix]; @@ -328,7 +323,6 @@ void R_DrawSurfaceBlock8_mip1 (void) { int v, i, b, lightstep, lighttemp, light; pixel_t pix, *psource, *prowdest; - char transtexture = r_transtexture; psource = pbasesource; prowdest = prowdestbase; @@ -353,8 +347,6 @@ void R_DrawSurfaceBlock8_mip1 (void) for (b=7; b>=0; b--) { pix = psource[b]; - if( transtexture ) - pix = pix << 3; prowdest[b] = pix; //((unsigned char *)vid.colormap) //[(light & 0xFF00) + pix]; @@ -382,7 +374,6 @@ void R_DrawSurfaceBlock8_mip2 (void) { int v, i, b, lightstep, lighttemp, light; pixel_t pix, *psource, *prowdest; - char transtexture = r_transtexture; psource = pbasesource; prowdest = prowdestbase; @@ -407,8 +398,6 @@ void R_DrawSurfaceBlock8_mip2 (void) for (b=3; b>=0; b--) { pix = psource[b]; - if( transtexture ) - pix = pix << 3; prowdest[b] = pix; //((unsigned char *)vid.colormap) //[(light & 0xFF00) + pix]; @@ -436,7 +425,6 @@ void R_DrawSurfaceBlock8_mip3 (void) { int v, i, b, lightstep, lighttemp, light; pixel_t pix, *psource, *prowdest; - char transtexture = r_transtexture; psource = pbasesource; prowdest = prowdestbase; @@ -461,8 +449,6 @@ void R_DrawSurfaceBlock8_mip3 (void) for (b=1; b>=0; b--) { pix = psource[b]; - if( transtexture ) - pix = pix << 3; prowdest[b] = pix; //((unsigned char *)vid.colormap) //[(light & 0xFF00) + pix]; From 65cf77c32b776d84f8e2e67647c08c834342833f Mon Sep 17 00:00:00 2001 From: mittorn Date: Sun, 24 Mar 2019 02:03:29 +0700 Subject: [PATCH 019/115] ref_soft: declare r_bsp.c functions --- r_local.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/r_local.h b/r_local.h index 932f3aa7..4f034351 100644 --- a/r_local.h +++ b/r_local.h @@ -1242,7 +1242,11 @@ extern vec3_t r_entorigin; extern int r_leafkeys[MAX_MAP_LEAFS]; #define LEAF_KEY(pleaf) r_leafkeys[(pleaf - WORLDMODEL->leafs)] - +// +// r_bsp.c +// +void R_RotateBmodel (void); +void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel, mnode_t *topnode); // // r_blitscreen.c // From 3617e8e7a105b0bfab6f9b48b48848c2bb592a56 Mon Sep 17 00:00:00 2001 From: mittorn Date: Mon, 25 Mar 2019 03:34:30 +0700 Subject: [PATCH 020/115] ref_soft: REF_SOFTWARE, resize support --- r_context.c | 2 +- r_draw.c | 4 +- r_glblit.c | 172 ++++++++++++++++++++++++++++++++++++++++++---------- r_local.h | 5 +- r_main.c | 14 ++--- r_surf.c | 13 +++- 6 files changed, 165 insertions(+), 45 deletions(-) diff --git a/r_context.c b/r_context.c index 65821e7c..9f71afae 100644 --- a/r_context.c +++ b/r_context.c @@ -326,7 +326,7 @@ void GL_SetTexCoordArrayMode() void GL_OnContextCreated() { - R_InitBlit(); + //R_InitBlit(); } diff --git a/r_draw.c b/r_draw.c index 26f9cbe9..2f6fb211 100644 --- a/r_draw.c +++ b/r_draw.c @@ -118,11 +118,13 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, #pragma omp parallel for schedule(static) for (v=0 ; vwidth + s1; + { f = 0; fstep = s2*0x10000/w; @@ -144,7 +146,7 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, for (u=0 ; u>16]; - int alpha = vid.alpha; + int alpha = alpha1; f += fstep; if( transparent ) diff --git a/r_glblit.c b/r_glblit.c index f3eb4f1d..7b57a68e 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -1,6 +1,13 @@ #include "r_local.h" #include "../ref_gl/gl_export.h" +struct swblit_s +{ + uint stride; + uint bpp; + uint rmask, gmask, bmask; +} swblit; + /* ======================== @@ -38,9 +45,35 @@ unsigned short *buffer; #define LOAD(x) p##x = gEngfuncs.GL_GetProcAddress(#x) -void R_BuildScreenMap() +static int FIRST_BIT( uint mask ) +{ + uint i; + + for( i = 0; !(BIT(i) & mask); i++ ); + + return i; +} + +static int COUNT_BITS( uint mask ) +{ + uint i; + + for( i = 0; mask; mask = mask >> 1 ) + i += mask & 1; + + return i; +} + +void R_BuildScreenMap( void ) { int i; + uint rshift = FIRST_BIT(swblit.rmask), gshift = FIRST_BIT(swblit.gmask), bshift = FIRST_BIT(swblit.bmask); + uint rbits = COUNT_BITS(swblit.rmask), gbits = COUNT_BITS(swblit.gmask), bbits = COUNT_BITS(swblit.bmask); + uint rmult = BIT(rbits), gmult = BIT(gbits), bmult = BIT(bbits); + uint rdiv = MASK(5), gdiv = MASK(6), bdiv = MASK(5); + + gEngfuncs.Con_Printf("Blit table: %d %d %d %d %d %d\n", rmult, gmult, bmult, rdiv, gdiv, bdiv ); + #ifdef SEPARATE_BLIT for( i = 0; i < 256; i++ ) { @@ -69,16 +102,24 @@ void R_BuildScreenMap() r = ((i >> (8 - 3) )<< 2 ) & MASK(5); g = ((i >> (8 - 3 - 3)) << 3) & MASK(6); b = ((i >> (8 - 3 - 3 - 2)) << 3) & MASK(5); - major = r << (6 + 5) | (g << 5) | b; + //major = r << (6 + 5) | (g << 5) | b; + major = (r * rmult / rdiv) << rshift | (g * gmult / gdiv) << gshift | (b * bmult / bdiv) << bshift; for( j = 0; j < 256; j++ ) { + uint minor; // restore minor GBRGBRGB r = MOVE_BIT(j, 5, 1) | MOVE_BIT(j, 2, 0); g = MOVE_BIT(j, 7, 2) | MOVE_BIT(j, 4, 1) | MOVE_BIT(j, 1, 0); b = MOVE_BIT(j, 6, 2) | MOVE_BIT(j, 3, 1) | MOVE_BIT(j, 0, 0); - vid.screen[(i<<8)|j] = r << (6 + 5) | (g << 5) | b | major; + //vid.screen[(i<<8)|j] = r << (6 + 5) | (g << 5) | b | major; + minor = (r * rmult / rdiv) << rshift | (g * gmult / gdiv) << gshift | (b * bmult / bdiv) << bshift; + + if( swblit.bpp == 2 ) + vid.screen[(i<<8)|j] = major | minor; + else + vid.screen32[(i<<8)|j] = major | minor; } @@ -103,18 +144,18 @@ void R_BuildBlendMaps() r = r1 + r2; g = g1 + g2; b = b1 + b2; - if( r > MASK(2) ) - r = MASK(2); - if( g > MASK(2) ) - g = MASK(2); - if( b > MASK(1) ) - b = MASK(1); + if( r > MASK(3) ) + r = MASK(3); + if( g > MASK(3) ) + g = MASK(3); + if( b > MASK(2) ) + b = MASK(2); ASSERT(!vid.addmap[index2|index1]); vid.addmap[index2|index1] = r << (2 + 3) | g << 2 | b; - r = r1 * r2 / MASK(2); - g = g1 * g2 / MASK(2); - b = b1 * b2 / MASK(1); + r = r1 * r2 / MASK(3); + g = g1 * g2 / MASK(3); + b = b1 * b2 / MASK(2); vid.modmap[index2|index1] = r << (2 + 3) | g << 2 | b; @@ -130,10 +171,12 @@ void R_BuildBlendMaps() } } +void R_AllocScreen(); + void R_InitBlit() { - LOAD(glBegin); + /*LOAD(glBegin); LOAD(glEnd); LOAD(glTexCoord2f); LOAD(glVertex2f); @@ -149,7 +192,7 @@ void R_InitBlit() LOAD(glDebugMessageControlARB); LOAD(glGetError); LOAD(glGenTextures); - LOAD(glTexParameteri); + LOAD(glTexParameteri);*/ #ifdef GLDEBUG if( gpGlobals->developer ) { @@ -164,36 +207,100 @@ void R_InitBlit() pglDebugMessageControlARB( GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, true ); #endif - buffer = Mem_Malloc( r_temppool, 1920*1080*2 ); + //buffer = Mem_Malloc( r_temppool, 1920*1080*2 ); - R_BuildScreenMap(); R_BuildBlendMaps(); - d_pzbuffer = malloc(vid.width*vid.height*2); - R_InitCaches(); + R_AllocScreen(); +} + +void R_AllocScreen() +{ + if( gpGlobals->width < 320 ) + gpGlobals->width = 320; + if( gpGlobals->height < 200 ) + gpGlobals->height = 200; + R_InitCaches(); + gEngfuncs.SW_CreateBuffer( gpGlobals->width, gpGlobals->height, &swblit.stride, &swblit.bpp, + &swblit.rmask, &swblit.gmask, &swblit.bmask); + R_BuildScreenMap(); + vid.width = gpGlobals->width; + vid.height = gpGlobals->height; + vid.rowbytes = gpGlobals->width; // rowpixels + if( d_pzbuffer ) + Mem_Free( d_pzbuffer ); + d_pzbuffer = Mem_Calloc( r_temppool, vid.width*vid.height*2 + 64 ); + if( vid.buffer ) + Mem_Free( vid.buffer ); + + vid.buffer = Mem_Malloc( r_temppool, vid.width * vid.height*sizeof( pixel_t ) ); } void R_BlitScreen() { //memset( vid.buffer, 10, vid.width * vid.height ); - int i; - byte *buf = vid.buffer; + int u, v; + void *buffer = gEngfuncs.SW_LockBuffer(); + if( !buffer || gpGlobals->width != vid.width || gpGlobals->height != vid.height ) + { + R_AllocScreen(); + return; + } + //byte *buf = vid.buffer; - #pragma omp parallel for schedule(static) - for( i = 0; i < vid.width * vid.height;i++) + //#pragma omp parallel for schedule(static) + if( swblit.bpp == 2 ) { -#ifdef SEPARATE_BLIT - // need only 1024 bytes table, but slower - // wtf?? maybe some prefetch??? - byte major = buf[(i<<1)+1]; - byte minor = buf[(i<<1)]; + unsigned short *pbuf = buffer; + for( v = 0; v < vid.height;v++) + { + uint start = vid.rowbytes * v; + uint dstart = swblit.stride * v; + + for( u = 0; u < vid.width; u++ ) + { + unsigned int s = vid.screen[vid.buffer[start + u]]; + pbuf[dstart + u] = s; + } + } + } + else if( swblit.bpp == 4 ) + { + unsigned int *pbuf = buffer; - buffer[i] = vid.screen_major[major] |vid.screen_minor[minor]; -#else - buffer[i] = vid.screen[vid.buffer[i]]; -#endif + for( v = 0; v < vid.height;v++) + { + uint start = vid.rowbytes * v; + uint dstart = swblit.stride * v; + + for( u = 0; u < vid.width; u++ ) + { + unsigned int s = vid.screen32[vid.buffer[start + u]]; + pbuf[dstart + u] = s; + } + } + } + else if( swblit.bpp == 3 ) + { + byte *pbuf = buffer; + for( v = 0; v < vid.height;v++) + { + uint start = vid.rowbytes * v; + uint dstart = swblit.stride * v; + + for( u = 0; u < vid.width; u++ ) + { + unsigned int s = vid.screen32[vid.buffer[start + u]]; + pbuf[(dstart+u)*3] = s; + s = s >> 8; + pbuf[(dstart+u)*3+1] = s; + s = s >> 8; + pbuf[(dstart+u)*3+2] = s; + } + } } +#if 0 pglViewport( 0, 0, gpGlobals->width, gpGlobals->height ); pglMatrixMode( GL_PROJECTION ); pglLoadIdentity(); @@ -223,4 +330,7 @@ void R_BlitScreen() pglDisable( GL_TEXTURE_2D ); gEngfuncs.GL_SwapBuffers(); // memset( vid.buffer, 0, vid.width * vid.height * 2 ); +#else + gEngfuncs.SW_UnlockBuffer(); +#endif } diff --git a/r_local.h b/r_local.h index 4f034351..eab47d4d 100644 --- a/r_local.h +++ b/r_local.h @@ -93,7 +93,7 @@ extern byte *r_temppool; #define CULL_OTHER 4 // culled by other reason // bit operation helpers -#define MASK(x) (BIT(x+1)-1) +#define MASK(x) (BIT(x)-1) #define GET_BIT(s,b) ((s & (1 << b)) >> b) #define MOVE_BIT(s, f, t) (GET_BIT(s,f) << t ) @@ -140,6 +140,7 @@ typedef struct pixel_t screen_major[256]; #else pixel_t screen[256*256]; + unsigned int screen32[256*256]; #endif byte addmap[256*256]; byte modmap[256*256]; @@ -832,7 +833,7 @@ extern cvar_t *r_showhull; #define NEAR_CLIP 0.01 -#define MAXALIASVERTS 2000 // TODO: tune this +//#define MAXALIASVERTS 2000 // TODO: tune this #define ALIAS_Z_CLIP_PLANE 4 // turbulence stuff diff --git a/r_main.c b/r_main.c index 5521419d..64b3b329 100644 --- a/r_main.c +++ b/r_main.c @@ -458,7 +458,7 @@ static void R_Clear( int bitMask ) pglDepthFunc( GL_LEQUAL ); pglDepthRange( gldepthmin, gldepthmax ); #endif - memset( vid.buffer, 0, 1920*1080*2); + memset( vid.buffer, 0, vid.width * vid.height *2); } //============================================================================= @@ -1686,6 +1686,10 @@ int R_RenderFrame( const ref_viewpass_t *rvp ) if( r_norefresh->value ) return 1; + // prevent cache overrun + if( gpGlobals->height > vid.height || gpGlobals->width > vid.width ) + return 1; + // setup the initial render params R_SetupRefParams( rvp ); @@ -1842,12 +1846,7 @@ qboolean R_Init() // create the window and set up the context r_temppool = Mem_AllocPool( "ref_sw zone" ); - vid.width = 1920; - vid.height = 1080; - vid.rowbytes = 1920; // rowpixels - - vid.buffer = Mem_Malloc( r_temppool, 1920*1080*sizeof( pixel_t ) ); - if( !gEngfuncs.R_Init_Video( REF_GL )) // request GL context + if( !gEngfuncs.R_Init_Video( REF_SOFTWARE )) // request GL context { gEngfuncs.R_Free_Video(); @@ -1855,6 +1854,7 @@ qboolean R_Init() return false; } + R_InitBlit(); R_InitImages(); // init draw stack diff --git a/r_surf.c b/r_surf.c index 35503974..19a7edda 100644 --- a/r_surf.c +++ b/r_surf.c @@ -256,6 +256,8 @@ void R_DrawSurface (void) pcolumndest += horzblockstep; } + // test what if we have very slow cache building + //usleep(10000); } @@ -490,9 +492,9 @@ void R_InitCaches (void) } else { - size = SURFCACHE_SIZE_AT_320X240; + size = SURFCACHE_SIZE_AT_320X240 * 2; - pix =1920 * 1080 * 16; + pix = vid.width * vid.height * 2; if (pix > 64000) size += (pix-64000)*3; } @@ -503,7 +505,12 @@ void R_InitCaches (void) gEngfuncs.Con_Printf ("%ik surface cache\n", size/1024); sc_size = size; - sc_base = (surfcache_t *)malloc(size); + if( sc_base ) + { + D_FlushCaches(); + Mem_Free( sc_base ); + } + sc_base = (surfcache_t *)Mem_Calloc(r_temppool,size); sc_rover = sc_base; sc_base->next = NULL; From c36f4157933a5d0f4ccf0cd41082fe8a72066841 Mon Sep 17 00:00:00 2001 From: mittorn Date: Mon, 25 Mar 2019 11:46:37 +0700 Subject: [PATCH 021/115] ref_soft: Do not clip submodels with negative topnode content (fix crash on some maps) --- r_local.h | 2 ++ r_main.c | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/r_local.h b/r_local.h index eab47d4d..b560b39a 100644 --- a/r_local.h +++ b/r_local.h @@ -1248,6 +1248,8 @@ extern int r_leafkeys[MAX_MAP_LEAFS]; // void R_RotateBmodel (void); void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel, mnode_t *topnode); +void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags, mnode_t *topnode); + // // r_blitscreen.c // diff --git a/r_main.c b/r_main.c index 64b3b329..7b0339ec 100644 --- a/r_main.c +++ b/r_main.c @@ -1326,13 +1326,13 @@ void R_DrawBEntitiesOnList (void) // RI.currententity = tr.draw_list->solid_entities[i]; RI.currententity->topnode = topnode; //ASSERT( RI.currentmodel == tr.draw_list->solid_entities[i]->model ); - //if (topnode->contents >= 0) + if (topnode->contents >= 0) { // not a leaf; has to be clipped to the world BSP r_clipflags = clipflags; R_DrawSolidClippedSubmodelPolygons (RI.currentmodel, topnode); } - //else + else { // falls entirely in one leaf, so we just put all the // edges in the edge list and let 1/z sorting handle @@ -1340,7 +1340,7 @@ void R_DrawBEntitiesOnList (void) //ASSERT( RI.currentmodel == tr.draw_list->solid_entities[i]->model ); - //R_DrawSubmodelPolygons (RI.currentmodel, clipflags, topnode); + R_DrawSubmodelPolygons (RI.currentmodel, clipflags, topnode); } RI.currententity->topnode = NULL; From 513381a322da167efcbe4ac487bf78f6157e1d5f Mon Sep 17 00:00:00 2001 From: mittorn Date: Mon, 25 Mar 2019 11:59:25 +0700 Subject: [PATCH 022/115] ref_soft: Flush caches and clear textures on newmap correctly --- r_context.c | 4 ++-- r_local.h | 2 +- r_main.c | 2 ++ r_misc.c | 2 +- r_surf.c | 17 +++++++++-------- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/r_context.c b/r_context.c index 9f71afae..2f2a9693 100644 --- a/r_context.c +++ b/r_context.c @@ -283,8 +283,8 @@ void Mod_BrushUnloadTextures( model_t *mod ) if( !tx || tx->gl_texturenum == tr.defaultTexture ) continue; // free slot - //GL_FreeTexture( tx->gl_texturenum ); // main texture - //GL_FreeTexture( tx->fb_texturenum ); // luma texture + GL_FreeTexture( tx->gl_texturenum ); // main texture + GL_FreeTexture( tx->fb_texturenum ); // luma texture } } diff --git a/r_local.h b/r_local.h index b560b39a..6a670cad 100644 --- a/r_local.h +++ b/r_local.h @@ -1269,7 +1269,7 @@ void R_ScanEdges (void); // // r_surf.c // -void D_FlushCaches (void); +void D_FlushCaches( qboolean newmap ); // // r_draw.c diff --git a/r_main.c b/r_main.c index 7b0339ec..5ea7cd62 100644 --- a/r_main.c +++ b/r_main.c @@ -1767,6 +1767,8 @@ void R_NewMap (void) { r_viewcluster = -1; + D_FlushCaches( true ); + r_cnumsurfs = sw_maxsurfs->value; if (r_cnumsurfs <= MINSURFACES) diff --git a/r_misc.c b/r_misc.c index 931c532a..d9112e46 100644 --- a/r_misc.c +++ b/r_misc.c @@ -324,7 +324,7 @@ void R_SetupFrameQ (void) if (r_fullbright->flags & FCVAR_CHANGED) { r_fullbright->flags &= ~FCVAR_CHANGED; - D_FlushCaches (); // so all lighting changes + D_FlushCaches( false ); // so all lighting changes } r_framecount++; diff --git a/r_surf.c b/r_surf.c index 19a7edda..9a12c409 100644 --- a/r_surf.c +++ b/r_surf.c @@ -507,7 +507,7 @@ void R_InitCaches (void) sc_size = size; if( sc_base ) { - D_FlushCaches(); + D_FlushCaches( false ); Mem_Free( sc_base ); } sc_base = (surfcache_t *)Mem_Calloc(r_temppool,size); @@ -524,17 +524,18 @@ void R_InitCaches (void) D_FlushCaches ================== */ -void D_FlushCaches (void) +void D_FlushCaches( qboolean newmap ) { surfcache_t *c; - if (!sc_base) - return; - - for (c = sc_base ; c ; c = c->next) + // if newmap, surfaces already freed + if( !newmap ) { - if (c->owner) - *c->owner = NULL; + for(c = sc_base ; c ; c = c->next ) + { + if ( c->owner ) + *c->owner = NULL; + } } sc_rover = sc_base; From 3d8fe065b5c13b5ab042a12d66a95daf1f50e63c Mon Sep 17 00:00:00 2001 From: mittorn Date: Mon, 25 Mar 2019 21:18:47 +0700 Subject: [PATCH 023/115] ref_soft: Fix windows build --- r_context.c | 2 +- r_image.c | 6 ++++-- r_triapi.c | 5 +++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/r_context.c b/r_context.c index 2f2a9693..75158b3c 100644 --- a/r_context.c +++ b/r_context.c @@ -708,7 +708,7 @@ ref_interface_t gReffuncs = VGUI_GenerateTexture, }; -int GAME_EXPORT GetRefAPI( int version, ref_interface_t *funcs, ref_api_t *engfuncs, ref_globals_t *globals ) +int EXPORT GAME_EXPORT GetRefAPI( int version, ref_interface_t *funcs, ref_api_t *engfuncs, ref_globals_t *globals ) { if( version != REF_API_VERSION ) return 0; diff --git a/r_image.c b/r_image.c index 200b4eb7..17a840fd 100644 --- a/r_image.c +++ b/r_image.c @@ -493,6 +493,7 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) uint offset = 0; qboolean normalMap; const byte *bufend; + int mipCount; tex->fogParams[0] = pic->fogParams[0]; tex->fogParams[1] = pic->fogParams[1]; @@ -511,7 +512,7 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) buf = pic->buffer; - int mipCount = 4;//GL_CalcMipmapCount( tex, ( buf != NULL )); + mipCount = 4;//GL_CalcMipmapCount( tex, ( buf != NULL )); // NOTE: only single uncompressed textures can be resamples, no mips, no layers, no sides if(( tex->depth == 1 ) && ( pic->width != tex->width ) || ( pic->height != tex->height )) @@ -524,6 +525,7 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) // mips will be auto-generated if desired for( j = 0; j < mipCount; j++ ) { + int x, y; width = Q_max( 1, ( tex->width >> j )); height = Q_max( 1, ( tex->height >> j )); texsize = GL_CalcTextureSize( width, height, tex->depth ); @@ -532,7 +534,7 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) tex->pixels[j] = Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 64 ); if( j == 0 && tex->flags & TF_HAS_ALPHA ) tex->alpha_pixels = Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 64 ); - int x, y; + for(i = 0; i < height * width; i++ ) { diff --git a/r_triapi.c b/r_triapi.c index 7f405fb0..47b81e6c 100644 --- a/r_triapi.c +++ b/r_triapi.c @@ -134,6 +134,7 @@ void _TriColor4f( float rr, float gg, float bb, float aa ) { //pglColor4f( r, g, b, a ); unsigned short r,g,b; + unsigned int major, minor; vid.alpha = aa * 7; @@ -150,10 +151,10 @@ void _TriColor4f( float rr, float gg, float bb, float aa ) r = rr * 31, g = gg * 63, b = bb * 31; - unsigned int major = (((r >> 2) & MASK(3)) << 5) |( (( (g >> 3) & MASK(3)) << 2 ) )| (((b >> 3) & MASK(2))); + major = (((r >> 2) & MASK(3)) << 5) |( (( (g >> 3) & MASK(3)) << 2 ) )| (((b >> 3) & MASK(2))); // save minor GBRGBRGB - unsigned int minor = MOVE_BIT(r,1,5) | MOVE_BIT(r,0,2) | MOVE_BIT(g,2,7) | MOVE_BIT(g,1,4) | MOVE_BIT(g,0,1) | MOVE_BIT(b,2,6)| MOVE_BIT(b,1,3)|MOVE_BIT(b,0,0); + minor = MOVE_BIT(r,1,5) | MOVE_BIT(r,0,2) | MOVE_BIT(g,2,7) | MOVE_BIT(g,1,4) | MOVE_BIT(g,0,1) | MOVE_BIT(b,2,6)| MOVE_BIT(b,1,3)|MOVE_BIT(b,0,0); vid.color = major << 8 | (minor & 0xFF); } From 9ba39f65b3a4ffa0d9c4ae5efbe9b2dd8dceaa58 Mon Sep 17 00:00:00 2001 From: mittorn Date: Tue, 26 Mar 2019 03:12:35 +0700 Subject: [PATCH 024/115] ref_soft: Triangle drawing --- adivtab.h | 1077 +++++++++++++++++++++++++++++++++ r_aclip.c | 323 ++++++++++ r_local.h | 34 +- r_main.c | 47 ++ r_misc.c | 16 +- r_polyse.c | 1612 ++++++++++++++++++++++++++++++++++++++++++++++++++ r_trialias.c | 229 +++++++ 7 files changed, 3327 insertions(+), 11 deletions(-) create mode 100644 adivtab.h create mode 100644 r_aclip.c create mode 100644 r_polyse.c create mode 100644 r_trialias.c diff --git a/adivtab.h b/adivtab.h new file mode 100644 index 00000000..aad0c562 --- /dev/null +++ b/adivtab.h @@ -0,0 +1,1077 @@ +/* +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. + +*/ +// table of quotients and remainders for [-15...16] / [-15...16] + +// numerator = -15 +{1, 0}, +{1, -1}, +{1, -2}, +{1, -3}, +{1, -4}, +{1, -5}, +{1, -6}, +{1, -7}, +{2, -1}, +{2, -3}, +{3, 0}, +{3, -3}, +{5, 0}, +{7, -1}, +{15, 0}, +{0, 0}, +{-15, 0}, +{-8, 1}, +{-5, 0}, +{-4, 1}, +{-3, 0}, +{-3, 3}, +{-3, 6}, +{-2, 1}, +{-2, 3}, +{-2, 5}, +{-2, 7}, +{-2, 9}, +{-2, 11}, +{-2, 13}, +{-1, 0}, +{-1, 1}, +// numerator = -14 +{0, -14}, +{1, 0}, +{1, -1}, +{1, -2}, +{1, -3}, +{1, -4}, +{1, -5}, +{1, -6}, +{2, 0}, +{2, -2}, +{2, -4}, +{3, -2}, +{4, -2}, +{7, 0}, +{14, 0}, +{0, 0}, +{-14, 0}, +{-7, 0}, +{-5, 1}, +{-4, 2}, +{-3, 1}, +{-3, 4}, +{-2, 0}, +{-2, 2}, +{-2, 4}, +{-2, 6}, +{-2, 8}, +{-2, 10}, +{-2, 12}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +// numerator = -13 +{0, -13}, +{0, -13}, +{1, 0}, +{1, -1}, +{1, -2}, +{1, -3}, +{1, -4}, +{1, -5}, +{1, -6}, +{2, -1}, +{2, -3}, +{3, -1}, +{4, -1}, +{6, -1}, +{13, 0}, +{0, 0}, +{-13, 0}, +{-7, 1}, +{-5, 2}, +{-4, 3}, +{-3, 2}, +{-3, 5}, +{-2, 1}, +{-2, 3}, +{-2, 5}, +{-2, 7}, +{-2, 9}, +{-2, 11}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +// numerator = -12 +{0, -12}, +{0, -12}, +{0, -12}, +{1, 0}, +{1, -1}, +{1, -2}, +{1, -3}, +{1, -4}, +{1, -5}, +{2, 0}, +{2, -2}, +{3, 0}, +{4, 0}, +{6, 0}, +{12, 0}, +{0, 0}, +{-12, 0}, +{-6, 0}, +{-4, 0}, +{-3, 0}, +{-3, 3}, +{-2, 0}, +{-2, 2}, +{-2, 4}, +{-2, 6}, +{-2, 8}, +{-2, 10}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +// numerator = -11 +{0, -11}, +{0, -11}, +{0, -11}, +{0, -11}, +{1, 0}, +{1, -1}, +{1, -2}, +{1, -3}, +{1, -4}, +{1, -5}, +{2, -1}, +{2, -3}, +{3, -2}, +{5, -1}, +{11, 0}, +{0, 0}, +{-11, 0}, +{-6, 1}, +{-4, 1}, +{-3, 1}, +{-3, 4}, +{-2, 1}, +{-2, 3}, +{-2, 5}, +{-2, 7}, +{-2, 9}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +// numerator = -10 +{0, -10}, +{0, -10}, +{0, -10}, +{0, -10}, +{0, -10}, +{1, 0}, +{1, -1}, +{1, -2}, +{1, -3}, +{1, -4}, +{2, 0}, +{2, -2}, +{3, -1}, +{5, 0}, +{10, 0}, +{0, 0}, +{-10, 0}, +{-5, 0}, +{-4, 2}, +{-3, 2}, +{-2, 0}, +{-2, 2}, +{-2, 4}, +{-2, 6}, +{-2, 8}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +// numerator = -9 +{0, -9}, +{0, -9}, +{0, -9}, +{0, -9}, +{0, -9}, +{0, -9}, +{1, 0}, +{1, -1}, +{1, -2}, +{1, -3}, +{1, -4}, +{2, -1}, +{3, 0}, +{4, -1}, +{9, 0}, +{0, 0}, +{-9, 0}, +{-5, 1}, +{-3, 0}, +{-3, 3}, +{-2, 1}, +{-2, 3}, +{-2, 5}, +{-2, 7}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +{-1, 7}, +// numerator = -8 +{0, -8}, +{0, -8}, +{0, -8}, +{0, -8}, +{0, -8}, +{0, -8}, +{0, -8}, +{1, 0}, +{1, -1}, +{1, -2}, +{1, -3}, +{2, 0}, +{2, -2}, +{4, 0}, +{8, 0}, +{0, 0}, +{-8, 0}, +{-4, 0}, +{-3, 1}, +{-2, 0}, +{-2, 2}, +{-2, 4}, +{-2, 6}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +{-1, 7}, +{-1, 8}, +// numerator = -7 +{0, -7}, +{0, -7}, +{0, -7}, +{0, -7}, +{0, -7}, +{0, -7}, +{0, -7}, +{0, -7}, +{1, 0}, +{1, -1}, +{1, -2}, +{1, -3}, +{2, -1}, +{3, -1}, +{7, 0}, +{0, 0}, +{-7, 0}, +{-4, 1}, +{-3, 2}, +{-2, 1}, +{-2, 3}, +{-2, 5}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +{-1, 7}, +{-1, 8}, +{-1, 9}, +// numerator = -6 +{0, -6}, +{0, -6}, +{0, -6}, +{0, -6}, +{0, -6}, +{0, -6}, +{0, -6}, +{0, -6}, +{0, -6}, +{1, 0}, +{1, -1}, +{1, -2}, +{2, 0}, +{3, 0}, +{6, 0}, +{0, 0}, +{-6, 0}, +{-3, 0}, +{-2, 0}, +{-2, 2}, +{-2, 4}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +{-1, 7}, +{-1, 8}, +{-1, 9}, +{-1, 10}, +// numerator = -5 +{0, -5}, +{0, -5}, +{0, -5}, +{0, -5}, +{0, -5}, +{0, -5}, +{0, -5}, +{0, -5}, +{0, -5}, +{0, -5}, +{1, 0}, +{1, -1}, +{1, -2}, +{2, -1}, +{5, 0}, +{0, 0}, +{-5, 0}, +{-3, 1}, +{-2, 1}, +{-2, 3}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +{-1, 7}, +{-1, 8}, +{-1, 9}, +{-1, 10}, +{-1, 11}, +// numerator = -4 +{0, -4}, +{0, -4}, +{0, -4}, +{0, -4}, +{0, -4}, +{0, -4}, +{0, -4}, +{0, -4}, +{0, -4}, +{0, -4}, +{0, -4}, +{1, 0}, +{1, -1}, +{2, 0}, +{4, 0}, +{0, 0}, +{-4, 0}, +{-2, 0}, +{-2, 2}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +{-1, 7}, +{-1, 8}, +{-1, 9}, +{-1, 10}, +{-1, 11}, +{-1, 12}, +// numerator = -3 +{0, -3}, +{0, -3}, +{0, -3}, +{0, -3}, +{0, -3}, +{0, -3}, +{0, -3}, +{0, -3}, +{0, -3}, +{0, -3}, +{0, -3}, +{0, -3}, +{1, 0}, +{1, -1}, +{3, 0}, +{0, 0}, +{-3, 0}, +{-2, 1}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +{-1, 7}, +{-1, 8}, +{-1, 9}, +{-1, 10}, +{-1, 11}, +{-1, 12}, +{-1, 13}, +// numerator = -2 +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{0, -2}, +{1, 0}, +{2, 0}, +{0, 0}, +{-2, 0}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +{-1, 7}, +{-1, 8}, +{-1, 9}, +{-1, 10}, +{-1, 11}, +{-1, 12}, +{-1, 13}, +{-1, 14}, +// numerator = -1 +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{0, -1}, +{1, 0}, +{0, 0}, +{-1, 0}, +{-1, 1}, +{-1, 2}, +{-1, 3}, +{-1, 4}, +{-1, 5}, +{-1, 6}, +{-1, 7}, +{-1, 8}, +{-1, 9}, +{-1, 10}, +{-1, 11}, +{-1, 12}, +{-1, 13}, +{-1, 14}, +{-1, 15}, +// numerator = 0 +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +{0, 0}, +// numerator = 1 +{-1, -14}, +{-1, -13}, +{-1, -12}, +{-1, -11}, +{-1, -10}, +{-1, -9}, +{-1, -8}, +{-1, -7}, +{-1, -6}, +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{0, 0}, +{1, 0}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +{0, 1}, +// numerator = 2 +{-1, -13}, +{-1, -12}, +{-1, -11}, +{-1, -10}, +{-1, -9}, +{-1, -8}, +{-1, -7}, +{-1, -6}, +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, 0}, +{0, 0}, +{2, 0}, +{1, 0}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +{0, 2}, +// numerator = 3 +{-1, -12}, +{-1, -11}, +{-1, -10}, +{-1, -9}, +{-1, -8}, +{-1, -7}, +{-1, -6}, +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -1}, +{-3, 0}, +{0, 0}, +{3, 0}, +{1, 1}, +{1, 0}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +{0, 3}, +// numerator = 4 +{-1, -11}, +{-1, -10}, +{-1, -9}, +{-1, -8}, +{-1, -7}, +{-1, -6}, +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -2}, +{-2, 0}, +{-4, 0}, +{0, 0}, +{4, 0}, +{2, 0}, +{1, 1}, +{1, 0}, +{0, 4}, +{0, 4}, +{0, 4}, +{0, 4}, +{0, 4}, +{0, 4}, +{0, 4}, +{0, 4}, +{0, 4}, +{0, 4}, +{0, 4}, +{0, 4}, +// numerator = 5 +{-1, -10}, +{-1, -9}, +{-1, -8}, +{-1, -7}, +{-1, -6}, +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -3}, +{-2, -1}, +{-3, -1}, +{-5, 0}, +{0, 0}, +{5, 0}, +{2, 1}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 5}, +{0, 5}, +{0, 5}, +{0, 5}, +{0, 5}, +{0, 5}, +{0, 5}, +{0, 5}, +{0, 5}, +{0, 5}, +{0, 5}, +// numerator = 6 +{-1, -9}, +{-1, -8}, +{-1, -7}, +{-1, -6}, +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -4}, +{-2, -2}, +{-2, 0}, +{-3, 0}, +{-6, 0}, +{0, 0}, +{6, 0}, +{3, 0}, +{2, 0}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 6}, +{0, 6}, +{0, 6}, +{0, 6}, +{0, 6}, +{0, 6}, +{0, 6}, +{0, 6}, +{0, 6}, +{0, 6}, +// numerator = 7 +{-1, -8}, +{-1, -7}, +{-1, -6}, +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -5}, +{-2, -3}, +{-2, -1}, +{-3, -2}, +{-4, -1}, +{-7, 0}, +{0, 0}, +{7, 0}, +{3, 1}, +{2, 1}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 7}, +{0, 7}, +{0, 7}, +{0, 7}, +{0, 7}, +{0, 7}, +{0, 7}, +{0, 7}, +{0, 7}, +// numerator = 8 +{-1, -7}, +{-1, -6}, +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -6}, +{-2, -4}, +{-2, -2}, +{-2, 0}, +{-3, -1}, +{-4, 0}, +{-8, 0}, +{0, 0}, +{8, 0}, +{4, 0}, +{2, 2}, +{2, 0}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 8}, +{0, 8}, +{0, 8}, +{0, 8}, +{0, 8}, +{0, 8}, +{0, 8}, +{0, 8}, +// numerator = 9 +{-1, -6}, +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -7}, +{-2, -5}, +{-2, -3}, +{-2, -1}, +{-3, -3}, +{-3, 0}, +{-5, -1}, +{-9, 0}, +{0, 0}, +{9, 0}, +{4, 1}, +{3, 0}, +{2, 1}, +{1, 4}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 9}, +{0, 9}, +{0, 9}, +{0, 9}, +{0, 9}, +{0, 9}, +{0, 9}, +// numerator = 10 +{-1, -5}, +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -8}, +{-2, -6}, +{-2, -4}, +{-2, -2}, +{-2, 0}, +{-3, -2}, +{-4, -2}, +{-5, 0}, +{-10, 0}, +{0, 0}, +{10, 0}, +{5, 0}, +{3, 1}, +{2, 2}, +{2, 0}, +{1, 4}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 10}, +{0, 10}, +{0, 10}, +{0, 10}, +{0, 10}, +{0, 10}, +// numerator = 11 +{-1, -4}, +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -9}, +{-2, -7}, +{-2, -5}, +{-2, -3}, +{-2, -1}, +{-3, -4}, +{-3, -1}, +{-4, -1}, +{-6, -1}, +{-11, 0}, +{0, 0}, +{11, 0}, +{5, 1}, +{3, 2}, +{2, 3}, +{2, 1}, +{1, 5}, +{1, 4}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 11}, +{0, 11}, +{0, 11}, +{0, 11}, +{0, 11}, +// numerator = 12 +{-1, -3}, +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -10}, +{-2, -8}, +{-2, -6}, +{-2, -4}, +{-2, -2}, +{-2, 0}, +{-3, -3}, +{-3, 0}, +{-4, 0}, +{-6, 0}, +{-12, 0}, +{0, 0}, +{12, 0}, +{6, 0}, +{4, 0}, +{3, 0}, +{2, 2}, +{2, 0}, +{1, 5}, +{1, 4}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 12}, +{0, 12}, +{0, 12}, +{0, 12}, +// numerator = 13 +{-1, -2}, +{-1, -1}, +{-1, 0}, +{-2, -11}, +{-2, -9}, +{-2, -7}, +{-2, -5}, +{-2, -3}, +{-2, -1}, +{-3, -5}, +{-3, -2}, +{-4, -3}, +{-5, -2}, +{-7, -1}, +{-13, 0}, +{0, 0}, +{13, 0}, +{6, 1}, +{4, 1}, +{3, 1}, +{2, 3}, +{2, 1}, +{1, 6}, +{1, 5}, +{1, 4}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 13}, +{0, 13}, +{0, 13}, +// numerator = 14 +{-1, -1}, +{-1, 0}, +{-2, -12}, +{-2, -10}, +{-2, -8}, +{-2, -6}, +{-2, -4}, +{-2, -2}, +{-2, 0}, +{-3, -4}, +{-3, -1}, +{-4, -2}, +{-5, -1}, +{-7, 0}, +{-14, 0}, +{0, 0}, +{14, 0}, +{7, 0}, +{4, 2}, +{3, 2}, +{2, 4}, +{2, 2}, +{2, 0}, +{1, 6}, +{1, 5}, +{1, 4}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 14}, +{0, 14}, +// numerator = 15 +{-1, 0}, +{-2, -13}, +{-2, -11}, +{-2, -9}, +{-2, -7}, +{-2, -5}, +{-2, -3}, +{-2, -1}, +{-3, -6}, +{-3, -3}, +{-3, 0}, +{-4, -1}, +{-5, 0}, +{-8, -1}, +{-15, 0}, +{0, 0}, +{15, 0}, +{7, 1}, +{5, 0}, +{3, 3}, +{3, 0}, +{2, 3}, +{2, 1}, +{1, 7}, +{1, 6}, +{1, 5}, +{1, 4}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, +{0, 15}, +// numerator = 16 +{-2, -14}, +{-2, -12}, +{-2, -10}, +{-2, -8}, +{-2, -6}, +{-2, -4}, +{-2, -2}, +{-2, 0}, +{-3, -5}, +{-3, -2}, +{-4, -4}, +{-4, 0}, +{-6, -2}, +{-8, 0}, +{-16, 0}, +{0, 0}, +{16, 0}, +{8, 0}, +{5, 1}, +{4, 0}, +{3, 1}, +{2, 4}, +{2, 2}, +{2, 0}, +{1, 7}, +{1, 6}, +{1, 5}, +{1, 4}, +{1, 3}, +{1, 2}, +{1, 1}, +{1, 0}, diff --git a/r_aclip.c b/r_aclip.c new file mode 100644 index 00000000..e807bd61 --- /dev/null +++ b/r_aclip.c @@ -0,0 +1,323 @@ +/* +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. + +*/ +// r_aclip.c: clip routines for drawing Alias models directly to the screen + +#include "r_local.h" + +static finalvert_t fv[2][8]; + +void R_AliasProjectAndClipTestFinalVert (finalvert_t *fv); +void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, + finalvert_t *out); +void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1, + finalvert_t *out); +void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, + finalvert_t *out); +void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, + finalvert_t *out); + + +/* +================ +R_Alias_clip_z + +pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex +================ +*/ +void R_Alias_clip_z (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) +{ + float scale; + + scale = (ALIAS_Z_CLIP_PLANE - pfv0->xyz[2]) / + (pfv1->xyz[2] - pfv0->xyz[2]); + + out->xyz[0] = pfv0->xyz[0] + (pfv1->xyz[0] - pfv0->xyz[0]) * scale; + out->xyz[1] = pfv0->xyz[1] + (pfv1->xyz[1] - pfv0->xyz[1]) * scale; + out->xyz[2] = ALIAS_Z_CLIP_PLANE; + + out->s = pfv0->s + (pfv1->s - pfv0->s) * scale; + out->t = pfv0->t + (pfv1->t - pfv0->t) * scale; + out->l = pfv0->l + (pfv1->l - pfv0->l) * scale; + + R_AliasProjectAndClipTestFinalVert (out); +} + + +#if !id386 + +void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) +{ + float scale; + + if (pfv0->v >= pfv1->v ) + { + scale = (float)(RI.aliasvrect.x - pfv0->u) / + (pfv1->u - pfv0->u); + out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5; + out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5; + out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5; + out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5; + out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5; + out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5; + } + else + { + scale = (float)(RI.aliasvrect.x - pfv1->u) / + (pfv0->u - pfv1->u); + out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5; + out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5; + out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5; + out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5; + out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5; + out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5; + } +} + + +void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) +{ + float scale; + + if ( pfv0->v >= pfv1->v ) + { + scale = (float)(RI.aliasvrectright - pfv0->u ) / + (pfv1->u - pfv0->u ); + out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5; + out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5; + out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5; + out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5; + out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5; + out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5; + } + else + { + scale = (float)(RI.aliasvrectright - pfv1->u ) / + (pfv0->u - pfv1->u ); + out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5; + out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5; + out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5; + out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5; + out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5; + out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5; + } +} + + +void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) +{ + float scale; + + if (pfv0->v >= pfv1->v) + { + scale = (float)(RI.aliasvrect.y - pfv0->v) / + (pfv1->v - pfv0->v); + out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5; + out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5; + out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5; + out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5; + out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5; + out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5; + } + else + { + scale = (float)(RI.aliasvrect.y - pfv1->v) / + (pfv0->v - pfv1->v); + out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5; + out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5; + out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5; + out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5; + out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5; + out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5; + } +} + + +void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1, + finalvert_t *out) +{ + float scale; + + if (pfv0->v >= pfv1->v) + { + scale = (float)(RI.aliasvrectbottom - pfv0->v) / + (pfv1->v - pfv0->v); + + out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5; + out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5; + out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5; + out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5; + out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5; + out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5; + } + else + { + scale = (float)(RI.aliasvrectbottom - pfv1->v) / + (pfv0->v - pfv1->v); + + out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5; + out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5; + out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5; + out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5; + out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5; + out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5; + } +} + +#endif + + +int R_AliasClip (finalvert_t *in, finalvert_t *out, int flag, int count, + void(*clip)(finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) ) +{ + int i,j,k; + int flags, oldflags; + + j = count-1; + k = 0; + for (i=0 ; i RI.aliasvrectright) + out[k].flags |= ALIAS_RIGHT_CLIP; + if (out[k].v > RI.aliasvrectbottom) + out[k].flags |= ALIAS_BOTTOM_CLIP; + k++; + } + if (!flags) + { + out[k] = in[i]; + k++; + } + } + + return k; +} + + +/* +================ +R_AliasClipTriangle +================ +*/ +void R_AliasClipTriangle (finalvert_t *index0, finalvert_t *index1, finalvert_t *index2) +{ + int i, k, pingpong; + unsigned clipflags; + +// copy vertexes and fix seam texture coordinates + fv[0][0] = *index0; + fv[0][1] = *index1; + fv[0][2] = *index2; + +// clip + clipflags = fv[0][0].flags | fv[0][1].flags | fv[0][2].flags; + + if (clipflags & ALIAS_Z_CLIP) + { + k = R_AliasClip (fv[0], fv[1], ALIAS_Z_CLIP, 3, R_Alias_clip_z); + if (k == 0) + return; + + pingpong = 1; + clipflags = fv[1][0].flags | fv[1][1].flags | fv[1][2].flags; + } + else + { + pingpong = 0; + k = 3; + } + + if (clipflags & ALIAS_LEFT_CLIP) + { + k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], + ALIAS_LEFT_CLIP, k, R_Alias_clip_left); + if (k == 0) + return; + + pingpong ^= 1; + } + + if (clipflags & ALIAS_RIGHT_CLIP) + { + k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], + ALIAS_RIGHT_CLIP, k, R_Alias_clip_right); + if (k == 0) + return; + + pingpong ^= 1; + } + + if (clipflags & ALIAS_BOTTOM_CLIP) + { + k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], + ALIAS_BOTTOM_CLIP, k, R_Alias_clip_bottom); + if (k == 0) + return; + + pingpong ^= 1; + } + + if (clipflags & ALIAS_TOP_CLIP) + { + k = R_AliasClip (fv[pingpong], fv[pingpong ^ 1], + ALIAS_TOP_CLIP, k, R_Alias_clip_top); + if (k == 0) + return; + + pingpong ^= 1; + } + + for (i=0 ; i RI.aliasvrectright) + fv[pingpong][i].u = RI.aliasvrectright; + + if (fv[pingpong][i].v < RI.aliasvrect.y) + fv[pingpong][i].v = RI.aliasvrect.y; + else if (fv[pingpong][i].v > RI.aliasvrectbottom) + fv[pingpong][i].v = RI.aliasvrectbottom; + + fv[pingpong][i].flags = 0; + } + +// draw triangles + for (i=1 ; ileafs)] + +extern int ubasestep, errorterm, erroradjustup, erroradjustdown; + + +extern mvertex_t *r_pcurrentvertbase; +extern int r_maxvalidedgeoffset; + +typedef struct +{ + finalvert_t *a, *b, *c; +} aliastriangleparms_t; + +extern aliastriangleparms_t aliastriangleparms; + + +extern int r_aliasblendcolor; + +extern float aliasxscale, aliasyscale, aliasxcenter, aliasycenter; + +void R_DrawTriangle( void ); +//void R_DrawTriangle (finalvert_t *index0, finalvert_t *index1, finalvert_t *index2); +void R_AliasClipTriangle (finalvert_t *index0, finalvert_t *index1, finalvert_t *index2); + // // r_bsp.c // @@ -1294,9 +1317,14 @@ void TransformVector (vec3_t in, vec3_t out); void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf); void R_RenderFace (msurface_t *fa, int clipflags); -#if id386 -#error aaa -#endif +// +// r_main.c +// +void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]); + + +void R_RenderTriangle( finalvert_t *pfv ); +void R_SetupFinalVert( finalvert_t *fv, float x, float y, float z, int light, int s, int t ); // // engine callbacks diff --git a/r_main.c b/r_main.c index 5ea7cd62..34c35cf6 100644 --- a/r_main.c +++ b/r_main.c @@ -130,6 +130,7 @@ int r_clipflags; byte r_warpbuffer[WARP_WIDTH * WARP_HEIGHT]; int r_numallocatededges; +float r_aliasuvscale = 1.0; /* ================ @@ -157,6 +158,39 @@ void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]) out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2]; } +/* +================ +R_ConcatTransforms +================ +*/ +void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]) +{ + out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + + in1[0][2] * in2[2][0]; + out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + + in1[0][2] * in2[2][1]; + out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + + in1[0][2] * in2[2][2]; + out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + + in1[0][2] * in2[2][3] + in1[0][3]; + out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + + in1[1][2] * in2[2][0]; + out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + + in1[1][2] * in2[2][1]; + out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + + in1[1][2] * in2[2][2]; + out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + + in1[1][2] * in2[2][3] + in1[1][3]; + out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + + in1[2][2] * in2[2][0]; + out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + + in1[2][2] * in2[2][1]; + out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + + in1[2][2] * in2[2][2]; + out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + + in1[2][2] * in2[2][3] + in1[2][3]; +} + @@ -991,6 +1025,19 @@ void R_DrawEntitiesOnList( void ) break; case mod_studio: //R_DrawStudioModel( RI.currententity ); + {finalvert_t fv[3]; + void R_AliasSetUpTransform (void); + extern void (*d_pdrawspans)(void *); + extern void R_PolysetFillSpans8 ( void * ); + d_pdrawspans = R_PolysetFillSpans8; + //RI.currententity = gEngfuncs.GetEntityByIndex(0); + R_AliasSetUpTransform(); + R_SetupFinalVert( &fv[0], -10, -10, 5, 0, 0, 0); + R_SetupFinalVert( &fv[1], -10, 10, 10, 0, 0, 0); + R_SetupFinalVert( &fv[2], 10, 10, -10, 0, 0, 0); + R_RenderTriangle( &fv ); + } + break; default: break; diff --git a/r_misc.c b/r_misc.c index d9112e46..fbccc98b 100644 --- a/r_misc.c +++ b/r_misc.c @@ -244,10 +244,10 @@ void R_ViewChanged (vrect_t *vr) RI.fvrectbottom = (float)RI.vrectbottom; RI.fvrectbottom_adj = (float)RI.vrectbottom - 0.5; - //RI.aliasvrect.x = (int)(RI.vrect.x * r_aliasuvscale); - //RI.aliasvrect.y = (int)(RI.vrect.y * r_aliasuvscale); - //RI.aliasvrect.width = (int)(RI.vrect.width * r_aliasuvscale); - //RI.aliasvrect.height = (int)(RI.vrect.height * r_aliasuvscale); + RI.aliasvrect.x = (int)(RI.vrect.x * r_aliasuvscale); + RI.aliasvrect.y = (int)(RI.vrect.y * r_aliasuvscale); + RI.aliasvrect.width = (int)(RI.vrect.width * r_aliasuvscale); + RI.aliasvrect.height = (int)(RI.vrect.height * r_aliasuvscale); RI.aliasvrectright = RI.aliasvrect.x + RI.aliasvrect.width; RI.aliasvrectbottom = RI.aliasvrect.y + @@ -264,17 +264,17 @@ void R_ViewChanged (vrect_t *vr) // buffer origin to get an exact edge to edge fill xcenter = ((float)RI.vrect.width * XCENTERING) + RI.vrect.x - 0.5; - //aliasxcenter = xcenter * r_aliasuvscale; + aliasxcenter = xcenter * r_aliasuvscale; ycenter = ((float)RI.vrect.height * YCENTERING) + RI.vrect.y - 0.5; -// aliasycenter = ycenter * r_aliasuvscale; + aliasycenter = ycenter * r_aliasuvscale; xscale = RI.vrect.width / RI.horizontalFieldOfView; -// aliasxscale = xscale * r_aliasuvscale; + aliasxscale = xscale * r_aliasuvscale; xscaleinv = 1.0 / xscale; yscale = xscale; -// aliasyscale = yscale * r_aliasuvscale; + aliasyscale = yscale * r_aliasuvscale; yscaleinv = 1.0 / yscale; xscaleshrink = (RI.vrect.width-6)/RI.horizontalFieldOfView; yscaleshrink = xscaleshrink; diff --git a/r_polyse.c b/r_polyse.c new file mode 100644 index 00000000..fed994a0 --- /dev/null +++ b/r_polyse.c @@ -0,0 +1,1612 @@ +/* +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. + +*/ +// d_polyset.c: routines for drawing sets of polygons sharing the same +// texture (used for Alias models) + +#include "r_local.h" +/* +int rand1k[] = { +#include "rand1k.h" +}; +*/ +#define MASK_1K 0x3FF + +int rand1k_index = 0; + +// TODO: put in span spilling to shrink list size +// !!! if this is changed, it must be changed in d_polysa.s too !!! +#define DPS_MAXSPANS MAXHEIGHT+1 + // 1 extra for spanpackage that marks end + +// !!! if this is changed, it must be changed in asm_draw.h too !!! +typedef struct { + void *pdest; + short *pz; + int count; + byte *ptex; + int sfrac, tfrac, light, zi; +} spanpackage_t; + +typedef struct { + int isflattop; + int numleftedges; + int *pleftedgevert0; + int *pleftedgevert1; + int *pleftedgevert2; + int numrightedges; + int *prightedgevert0; + int *prightedgevert1; + int *prightedgevert2; +} edgetable; + +aliastriangleparms_t aliastriangleparms; + +int r_p0[6], r_p1[6], r_p2[6]; + +byte *d_pcolormap; + +int d_aflatcolor; +int d_xdenom; + +edgetable *pedgetable; + +edgetable edgetables[12] = { + {0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2 }, + {0, 2, r_p1, r_p0, r_p2, 1, r_p1, r_p2, NULL}, + {1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL}, + {0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0 }, + {0, 2, r_p0, r_p2, r_p1, 1, r_p0, r_p1, NULL}, + {0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL}, + {0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1 }, + {0, 2, r_p2, r_p1, r_p0, 1, r_p2, r_p0, NULL}, + {0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL}, + {1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL}, + {1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL}, + {0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL}, +}; + +// FIXME: some of these can become statics +int a_sstepxfrac, a_tstepxfrac, r_lstepx, a_ststepxwhole; +int r_sstepx, r_tstepx, r_lstepy, r_sstepy, r_tstepy; +int r_zistepx, r_zistepy; +int d_aspancount, d_countextrastep; + +spanpackage_t *a_spans; +spanpackage_t *d_pedgespanpackage; +static int ystart; +pixel_t *d_pdest, *d_ptex; +short *d_pz; +int d_sfrac, d_tfrac, d_light, d_zi; +int d_ptexextrastep, d_sfracextrastep; +int d_tfracextrastep, d_lightextrastep, d_pdestextrastep; +int d_lightbasestep, d_pdestbasestep, d_ptexbasestep; +int d_sfracbasestep, d_tfracbasestep; +int d_ziextrastep, d_zibasestep; +int d_pzextrastep, d_pzbasestep; + +typedef struct { + int quotient; + int remainder; +} adivtab_t; + +static adivtab_t adivtab[32*32] = { +#include "adivtab.h" +}; + +byte *skintable[MAX_LBM_HEIGHT]; +int skinwidth; +byte *skinstart; + +void (*d_pdrawspans)(spanpackage_t *pspanpackage); + +void R_PolysetDrawSpans8_33 (spanpackage_t *pspanpackage); +void R_PolysetDrawSpans8_66 (spanpackage_t *pspanpackage); +void R_PolysetDrawSpans8_Opaque (spanpackage_t *pspanpackage); + +void R_PolysetDrawThreshSpans8 (spanpackage_t *pspanpackage); +void R_PolysetCalcGradients (int skinwidth); +void R_DrawNonSubdiv (void); +void R_PolysetSetEdgeTable (void); +void R_RasterizeAliasPolySmooth (void); +void R_PolysetScanLeftEdge(int height); +void R_PolysetScanLeftEdge_C(int height); + +// ====================== +// PGM +// 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 +byte iractive = 0; +byte irtable[256] = { 79, 78, 77, 76, 75, 74, 73, 72, // black/white + 71, 70, 69, 68, 67, 66, 65, 64, + 64, 65, 66, 67, 68, 69, 70, 71, // dark taupe + 72, 73, 74, 75, 76, 77, 78, 79, + + 64, 65, 66, 67, 68, 69, 70, 71, // slate grey + 72, 73, 74, 75, 76, 77, 78, 79, + 208, 208, 208, 208, 208, 208, 208, 208, // unused?' + 64, 66, 68, 70, 72, 74, 76, 78, // dark yellow + + 64, 65, 66, 67, 68, 69, 70, 71, // dark red + 72, 73, 74, 75, 76, 77, 78, 79, + 64, 65, 66, 67, 68, 69, 70, 71, // grey/tan + 72, 73, 74, 75, 76, 77, 78, 79, + + 64, 66, 68, 70, 72, 74, 76, 78, // chocolate + 68, 67, 66, 65, 64, 65, 66, 67, // mauve / teal + 68, 69, 70, 71, 72, 73, 74, 75, + 76, 76, 77, 77, 78, 78, 79, 79, + + 64, 65, 66, 67, 68, 69, 70, 71, // more mauve + 72, 73, 74, 75, 76, 77, 78, 79, + 64, 65, 66, 67, 68, 69, 70, 71, // olive + 72, 73, 74, 75, 76, 77, 78, 79, + + 64, 65, 66, 67, 68, 69, 70, 71, // maroon + 72, 73, 74, 75, 76, 77, 78, 79, + 64, 65, 66, 67, 68, 69, 70, 71, // sky blue + 72, 73, 74, 75, 76, 77, 78, 79, + + 64, 65, 66, 67, 68, 69, 70, 71, // olive again + 72, 73, 74, 75, 76, 77, 78, 79, + 64, 65, 66, 67, 68, 69, 70, 71, // nuclear green + 64, 65, 66, 67, 68, 69, 70, 71, // bright yellow + + 64, 65, 66, 67, 68, 69, 70, 71, // fire colors + 72, 73, 74, 75, 76, 77, 78, 79, + 208, 208, 64, 64, 70, 71, 72, 64, // mishmash1 + 66, 68, 70, 64, 65, 66, 67, 68}; // mishmash2 +// PGM +// ====================== + +/* +================ +R_PolysetUpdateTables +================ +*/ +void R_PolysetUpdateTables (void) +{ + int i; + byte *s; + + if (r_affinetridesc.skinwidth != skinwidth || + r_affinetridesc.pskin != skinstart) + { + skinwidth = r_affinetridesc.skinwidth; + skinstart = r_affinetridesc.pskin; + s = skinstart; + for (i=0 ; iv[1] - aliastriangleparms.b->v[1] ) * ( aliastriangleparms.a->v[0] - aliastriangleparms.c->v[0] ) - + ( aliastriangleparms.a->v[0] - aliastriangleparms.b->v[0] ) * ( aliastriangleparms.a->v[1] - aliastriangleparms.c->v[1] ); + */ + + dv0_ab = aliastriangleparms.a->u - aliastriangleparms.b->u; + dv1_ab = aliastriangleparms.a->v - aliastriangleparms.b->v; + + if ( !( dv0_ab | dv1_ab ) ) + return; + + dv0_ac = aliastriangleparms.a->u - aliastriangleparms.c->u; + dv1_ac = aliastriangleparms.a->v - aliastriangleparms.c->v; + + if ( !( dv0_ac | dv1_ac ) ) + return; + + d_xdenom = ( dv0_ac * dv1_ab ) - ( dv0_ab * dv1_ac ); + + if ( d_xdenom < 0 ) + { + a_spans = spans; + + r_p0[0] = aliastriangleparms.a->u; // u + r_p0[1] = aliastriangleparms.a->v; // v + r_p0[2] = aliastriangleparms.a->s; // s + r_p0[3] = aliastriangleparms.a->t; // t + r_p0[4] = aliastriangleparms.a->l; // light + r_p0[5] = aliastriangleparms.a->zi; // iz + + r_p1[0] = aliastriangleparms.b->u; + r_p1[1] = aliastriangleparms.b->v; + r_p1[2] = aliastriangleparms.b->s; + r_p1[3] = aliastriangleparms.b->t; + r_p1[4] = aliastriangleparms.b->l; + r_p1[5] = aliastriangleparms.b->zi; + + r_p2[0] = aliastriangleparms.c->u; + r_p2[1] = aliastriangleparms.c->v; + r_p2[2] = aliastriangleparms.c->s; + r_p2[3] = aliastriangleparms.c->t; + r_p2[4] = aliastriangleparms.c->l; + r_p2[5] = aliastriangleparms.c->zi; + + R_PolysetSetEdgeTable (); + R_RasterizeAliasPolySmooth (); + } +} + + +/* +=================== +R_PolysetScanLeftEdge_C +==================== +*/ +void R_PolysetScanLeftEdge_C(int height) +{ + do + { + d_pedgespanpackage->pdest = d_pdest; + d_pedgespanpackage->pz = d_pz; + d_pedgespanpackage->count = d_aspancount; + d_pedgespanpackage->ptex = d_ptex; + + d_pedgespanpackage->sfrac = d_sfrac; + d_pedgespanpackage->tfrac = d_tfrac; + + // FIXME: need to clamp l, s, t, at both ends? + d_pedgespanpackage->light = d_light; + d_pedgespanpackage->zi = d_zi; + + d_pedgespanpackage++; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_pdest += d_pdestextrastep; + d_pz += d_pzextrastep; + d_aspancount += d_countextrastep; + d_ptex += d_ptexextrastep; + d_sfrac += d_sfracextrastep; + d_ptex += d_sfrac >> 16; + + d_sfrac &= 0xFFFF; + d_tfrac += d_tfracextrastep; + if (d_tfrac & 0x10000) + { + d_ptex += r_affinetridesc.skinwidth; + d_tfrac &= 0xFFFF; + } + d_light += d_lightextrastep; + d_zi += d_ziextrastep; + errorterm -= erroradjustdown; + } + else + { + d_pdest += d_pdestbasestep; + d_pz += d_pzbasestep; + d_aspancount += ubasestep; + d_ptex += d_ptexbasestep; + d_sfrac += d_sfracbasestep; + d_ptex += d_sfrac >> 16; + d_sfrac &= 0xFFFF; + d_tfrac += d_tfracbasestep; + if (d_tfrac & 0x10000) + { + d_ptex += r_affinetridesc.skinwidth; + d_tfrac &= 0xFFFF; + } + d_light += d_lightbasestep; + d_zi += d_zibasestep; + } + } while (--height); +} + +/* +=================== +FloorDivMod + +Returns mathematically correct (floor-based) quotient and remainder for +numer and denom, both of which should contain no fractional part. The +quotient must fit in 32 bits. +FIXME: GET RID OF THIS! (FloorDivMod) +==================== +*/ +void FloorDivMod (float numer, float denom, int *quotient, + int *rem) +{ + int q, r; + float x; + + if (numer >= 0.0) + { + + x = floor(numer / denom); + q = (int)x; + r = (int)floor(numer - (x * denom)); + } + else + { + // + // perform operations with positive values, and fix mod to make floor-based + // + x = floor(-numer / denom); + q = -(int)x; + r = (int)floor(-numer - (x * denom)); + if (r != 0) + { + q--; + r = (int)denom - r; + } + } + + *quotient = q; + *rem = r; +} + + +/* +=================== +R_PolysetSetUpForLineScan +==================== +*/ +void R_PolysetSetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv, + fixed8_t endvertu, fixed8_t endvertv) +{ + float dm, dn; + int tm, tn; + adivtab_t *ptemp; + +// TODO: implement x86 version + + errorterm = -1; + + tm = endvertu - startvertu; + tn = endvertv - startvertv; + + if (((tm <= 16) && (tm >= -15)) && + ((tn <= 16) && (tn >= -15))) + { + ptemp = &adivtab[((tm+15) << 5) + (tn+15)]; + ubasestep = ptemp->quotient; + erroradjustup = ptemp->remainder; + erroradjustdown = tn; + } + else + { + dm = tm; + dn = tn; + + FloorDivMod (dm, dn, &ubasestep, &erroradjustup); + + erroradjustdown = dn; + } +} + + + +/* +================ +R_PolysetCalcGradients +================ +*/ +#if id386 && !defined __linux__ +void R_PolysetCalcGradients( int skinwidth ) +{ + static float xstepdenominv, ystepdenominv, t0, t1; + static float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20; + static float one = 1.0F, negative_one = -1.0F; + static unsigned long t0_int, t1_int; + + extern unsigned long fpu_sp24_ceil_cw, fpu_ceil_cw, fpu_chop_cw; + + /* + p00_minus_p20 = r_p0[0] - r_p2[0]; + p01_minus_p21 = r_p0[1] - r_p2[1]; + p10_minus_p20 = r_p1[0] - r_p2[0]; + p11_minus_p21 = r_p1[1] - r_p2[1]; + */ + + __asm mov eax, dword ptr [r_p0+0] + __asm mov ebx, dword ptr [r_p0+4] + __asm sub eax, dword ptr [r_p2+0] + __asm sub ebx, dword ptr [r_p2+4] + __asm mov p00_minus_p20, eax + __asm mov p01_minus_p21, ebx + __asm fild dword ptr p00_minus_p20 + __asm fild dword ptr p01_minus_p21 + __asm mov eax, dword ptr [r_p1+0] + __asm mov ebx, dword ptr [r_p1+4] + __asm sub eax, dword ptr [r_p2+0] + __asm sub ebx, dword ptr [r_p2+4] + __asm fstp p01_minus_p21 + __asm fstp p00_minus_p20 + __asm mov p10_minus_p20, eax + __asm mov p11_minus_p21, ebx + __asm fild dword ptr p10_minus_p20 + __asm fild dword ptr p11_minus_p21 + __asm fstp p11_minus_p21 + __asm fstp p10_minus_p20 + + /* + xstepdenominv = 1.0 / (float)d_xdenom; + + ystepdenominv = -xstepdenominv; + */ + + /* + ** put FPU in single precision ceil mode + */ + __asm fldcw word ptr [fpu_sp24_ceil_cw] +// __asm fldcw word ptr [fpu_ceil_cw] + + __asm fild dword ptr d_xdenom ; d_xdenom + __asm fdivr one ; 1 / d_xdenom + __asm fst xstepdenominv ; + __asm fmul negative_one ; -( 1 / d_xdenom ) + +// ceil () for light so positive steps are exaggerated, negative steps +// diminished, pushing us away from underflow toward overflow. Underflow is +// very visible, overflow is very unlikely, because of ambient lighting + /* + t0 = r_p0[4] - r_p2[4]; + t1 = r_p1[4] - r_p2[4]; + r_lstepx = (int) + ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv); + r_lstepy = (int) + ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv); + */ + __asm mov eax, dword ptr [r_p0+16] + __asm mov ebx, dword ptr [r_p1+16] + __asm sub eax, dword ptr [r_p2+16] + __asm sub ebx, dword ptr [r_p2+16] + + __asm fstp ystepdenominv ; (empty) + + __asm mov t0_int, eax + __asm mov t1_int, ebx + __asm fild t0_int ; t0 + __asm fild t1_int ; t1 | t0 + __asm fxch st(1) ; t0 | t1 + __asm fstp t0 ; t1 + __asm fst t1 ; t1 + __asm fmul p01_minus_p21 ; t1 * p01_minus_p21 + __asm fld t0 ; t0 | t1 * p01_minus_p21 + __asm fmul p11_minus_p21 ; t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fld t1 ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fmul p00_minus_p20 ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fld t0 ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fmul p10_minus_p20 ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fxch st(2) ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 + __asm fsubp st(3), st ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21 + __asm fsubrp st(1), st ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21 + __asm fxch st(1) ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20 + __asm fmul xstepdenominv ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20 + __asm fxch st(1) + __asm fmul ystepdenominv ; r_lstepy | r_lstepx + __asm fxch st(1) ; r_lstepx | r_lstepy + __asm fistp dword ptr [r_lstepx] + __asm fistp dword ptr [r_lstepy] + + /* + ** put FPU back into extended precision chop mode + */ + __asm fldcw word ptr [fpu_chop_cw] + + /* + t0 = r_p0[2] - r_p2[2]; + t1 = r_p1[2] - r_p2[2]; + r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * + xstepdenominv); + r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) * + ystepdenominv); + */ + __asm mov eax, dword ptr [r_p0+8] + __asm mov ebx, dword ptr [r_p1+8] + __asm sub eax, dword ptr [r_p2+8] + __asm sub ebx, dword ptr [r_p2+8] + __asm mov t0_int, eax + __asm mov t1_int, ebx + __asm fild t0_int ; t0 + __asm fild t1_int ; t1 | t0 + __asm fxch st(1) ; t0 | t1 + __asm fstp t0 ; t1 + __asm fst t1 ; (empty) + + __asm fmul p01_minus_p21 ; t1 * p01_minus_p21 + __asm fld t0 ; t0 | t1 * p01_minus_p21 + __asm fmul p11_minus_p21 ; t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fld t1 ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fmul p00_minus_p20 ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fld t0 ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fmul p10_minus_p20 ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fxch st(2) ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 + __asm fsubp st(3), st ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21 + __asm fsubrp st(1), st ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21 + __asm fxch st(1) ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20 + __asm fmul xstepdenominv ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20 + __asm fxch st(1) + __asm fmul ystepdenominv ; r_lstepy | r_lstepx + __asm fxch st(1) ; r_lstepx | r_lstepy + __asm fistp dword ptr [r_sstepx] + __asm fistp dword ptr [r_sstepy] + + /* + t0 = r_p0[3] - r_p2[3]; + t1 = r_p1[3] - r_p2[3]; + r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * + xstepdenominv); + r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * + ystepdenominv); + */ + __asm mov eax, dword ptr [r_p0+12] + __asm mov ebx, dword ptr [r_p1+12] + __asm sub eax, dword ptr [r_p2+12] + __asm sub ebx, dword ptr [r_p2+12] + + __asm mov t0_int, eax + __asm mov t1_int, ebx + __asm fild t0_int ; t0 + __asm fild t1_int ; t1 | t0 + __asm fxch st(1) ; t0 | t1 + __asm fstp t0 ; t1 + __asm fst t1 ; (empty) + + __asm fmul p01_minus_p21 ; t1 * p01_minus_p21 + __asm fld t0 ; t0 | t1 * p01_minus_p21 + __asm fmul p11_minus_p21 ; t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fld t1 ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fmul p00_minus_p20 ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fld t0 ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fmul p10_minus_p20 ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fxch st(2) ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 + __asm fsubp st(3), st ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21 + __asm fsubrp st(1), st ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21 + __asm fxch st(1) ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20 + __asm fmul xstepdenominv ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20 + __asm fxch st(1) + __asm fmul ystepdenominv ; r_lstepy | r_lstepx + __asm fxch st(1) ; r_lstepx | r_lstepy + __asm fistp dword ptr [r_tstepx] + __asm fistp dword ptr [r_tstepy] + + /* + t0 = r_p0[5] - r_p2[5]; + t1 = r_p1[5] - r_p2[5]; + r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * + xstepdenominv); + r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * + ystepdenominv); + */ + __asm mov eax, dword ptr [r_p0+20] + __asm mov ebx, dword ptr [r_p1+20] + __asm sub eax, dword ptr [r_p2+20] + __asm sub ebx, dword ptr [r_p2+20] + + __asm mov t0_int, eax + __asm mov t1_int, ebx + __asm fild t0_int ; t0 + __asm fild t1_int ; t1 | t0 + __asm fxch st(1) ; t0 | t1 + __asm fstp t0 ; t1 + __asm fst t1 ; (empty) + + __asm fmul p01_minus_p21 ; t1 * p01_minus_p21 + __asm fld t0 ; t0 | t1 * p01_minus_p21 + __asm fmul p11_minus_p21 ; t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fld t1 ; t1 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fmul p00_minus_p20 ; t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fld t0 ; t0 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fmul p10_minus_p20 ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t0 * p11_minus_p21 | t1 * p01_minus_p21 + __asm fxch st(2) ; t0 * p11_minus_p21 | t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 + __asm fsubp st(3), st ; t0 * p10_minus_p20 | t1 * p00_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21 + __asm fsubrp st(1), st ; t1 * p00_minus_p20 - t0 * p10_minus_p20 | t1 * p01_minus_p21 - t0 * p11_minus_p21 + __asm fxch st(1) ; t1 * p01_minus_p21 - t0 * p11_minus_p21 | t1 * p00_minus_p20 - t0 * p10_minus_p20 + __asm fmul xstepdenominv ; r_lstepx | t1 * p00_minus_p20 - t0 * p10_minus_p20 + __asm fxch st(1) + __asm fmul ystepdenominv ; r_lstepy | r_lstepx + __asm fxch st(1) ; r_lstepx | r_lstepy + __asm fistp dword ptr [r_zistepx] + __asm fistp dword ptr [r_zistepy] + + /* +#if id386ALIAS + a_sstepxfrac = r_sstepx << 16; + a_tstepxfrac = r_tstepx << 16; +#else + a_sstepxfrac = r_sstepx & 0xFFFF; + a_tstepxfrac = r_tstepx & 0xFFFF; +#endif + */ + __asm mov eax, d_pdrawspans + __asm cmp eax, offset R_PolysetDrawSpans8_Opaque + __asm mov eax, r_sstepx + __asm mov ebx, r_tstepx + __asm jne translucent +//#if id386ALIAS + __asm shl eax, 16 + __asm shl ebx, 16 + __asm jmp done_with_steps +//#else +translucent: + __asm and eax, 0ffffh + __asm and ebx, 0ffffh +//#endif +done_with_steps: + __asm mov a_sstepxfrac, eax + __asm mov a_tstepxfrac, ebx + + /* + a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16); + */ + __asm mov ebx, r_tstepx + __asm mov ecx, r_sstepx + __asm sar ebx, 16 + __asm mov eax, skinwidth + __asm mul ebx + __asm sar ecx, 16 + __asm add eax, ecx + __asm mov a_ststepxwhole, eax +} +#else +void R_PolysetCalcGradients (int skinwidth) +{ + float xstepdenominv, ystepdenominv, t0, t1; + float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20; + + p00_minus_p20 = r_p0[0] - r_p2[0]; + p01_minus_p21 = r_p0[1] - r_p2[1]; + p10_minus_p20 = r_p1[0] - r_p2[0]; + p11_minus_p21 = r_p1[1] - r_p2[1]; + + xstepdenominv = 1.0 / (float)d_xdenom; + + ystepdenominv = -xstepdenominv; + +// ceil () for light so positive steps are exaggerated, negative steps +// diminished, pushing us away from underflow toward overflow. Underflow is +// very visible, overflow is very unlikely, because of ambient lighting + t0 = r_p0[4] - r_p2[4]; + t1 = r_p1[4] - r_p2[4]; + r_lstepx = (int) + ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv); + r_lstepy = (int) + ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv); + + t0 = r_p0[2] - r_p2[2]; + t1 = r_p1[2] - r_p2[2]; + r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * + xstepdenominv); + r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) * + ystepdenominv); + + t0 = r_p0[3] - r_p2[3]; + t1 = r_p1[3] - r_p2[3]; + r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * + xstepdenominv); + r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * + ystepdenominv); + + t0 = r_p0[5] - r_p2[5]; + t1 = r_p1[5] - r_p2[5]; + r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) * + xstepdenominv); + r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * + ystepdenominv); + +//#if id386ALIAS +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + a_sstepxfrac = r_sstepx << 16; + a_tstepxfrac = r_tstepx << 16; + } + else +#endif + { +//#else + a_sstepxfrac = r_sstepx & 0xFFFF; + a_tstepxfrac = r_tstepx & 0xFFFF; + } +//#endif + + a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16); +} +#endif + +/* +================ +R_PolysetDrawThreshSpans8 + +Random fizzle fade rasterizer +================ +*/ +void R_PolysetDrawThreshSpans8 (spanpackage_t *pspanpackage) +{ + int lcount; + byte *lpdest; + byte *lptex; + int lsfrac, ltfrac; + int llight; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + { + d_aspancount += ubasestep; + } + + if (lcount) + { + lpdest = pspanpackage->pdest; + lptex = pspanpackage->ptex; + lpz = pspanpackage->pz; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + llight = pspanpackage->light; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) >= *lpz) + { + rand1k_index = (rand1k_index + 1) & MASK_1K; + + /*if (rand1k[rand1k_index] <= r_affinetridesc.vis_thresh) + { + *lpdest = ((byte *)vid.colormap)[*lptex + (llight & 0xFF00)]; + *lpz = lzi >> 16; + }*/ + } + + lpdest++; + lzi += r_zistepx; + lpz++; + llight += r_lstepx; + lptex += a_ststepxwhole; + lsfrac += a_sstepxfrac; + lptex += lsfrac >> 16; + lsfrac &= 0xFFFF; + ltfrac += a_tstepxfrac; + if (ltfrac & 0x10000) + { + lptex += r_affinetridesc.skinwidth; + ltfrac &= 0xFFFF; + } + } while (--lcount); + } + + pspanpackage++; + } while (pspanpackage->count != -999999); +} + + +/* +================ +R_PolysetDrawSpans8 +================ +*/ +void R_PolysetDrawSpans8_33( spanpackage_t *pspanpackage) +{ + int lcount; + byte *lpdest; + byte *lptex; + int lsfrac, ltfrac; + int llight; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + { + d_aspancount += ubasestep; + } + + if (lcount) + { + lpdest = pspanpackage->pdest; + lptex = pspanpackage->ptex; + lpz = pspanpackage->pz; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + llight = pspanpackage->light; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) >= *lpz) + { + int temp = vid.colormap[*lptex + ( llight & 0xFF00 )]; + + *lpdest = vid.alphamap[temp+ *lpdest*256]; + } + lpdest++; + lzi += r_zistepx; + lpz++; + llight += r_lstepx; + lptex += a_ststepxwhole; + lsfrac += a_sstepxfrac; + lptex += lsfrac >> 16; + lsfrac &= 0xFFFF; + ltfrac += a_tstepxfrac; + if (ltfrac & 0x10000) + { + lptex += r_affinetridesc.skinwidth; + ltfrac &= 0xFFFF; + } + } while (--lcount); + } + + pspanpackage++; + } while (pspanpackage->count != -999999); +} + +void R_PolysetDrawSpansConstant8_33( spanpackage_t *pspanpackage) +{ + int lcount; + byte *lpdest; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + { + d_aspancount += ubasestep; + } + + if (lcount) + { + lpdest = pspanpackage->pdest; + lpz = pspanpackage->pz; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) >= *lpz) + { + *lpdest = vid.alphamap[r_aliasblendcolor + *lpdest*256]; + } + lpdest++; + lzi += r_zistepx; + lpz++; + } while (--lcount); + } + + pspanpackage++; + } while (pspanpackage->count != -999999); +} + +void R_PolysetDrawSpans8_66(spanpackage_t *pspanpackage) +{ + int lcount; + byte *lpdest; + byte *lptex; + int lsfrac, ltfrac; + int llight; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + { + d_aspancount += ubasestep; + } + + if (lcount) + { + lpdest = pspanpackage->pdest; + lptex = pspanpackage->ptex; + lpz = pspanpackage->pz; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + llight = pspanpackage->light; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) >= *lpz) + { + int temp = vid.colormap[*lptex + ( llight & 0xFF00 )]; + + *lpdest = vid.alphamap[temp*256 + *lpdest]; + *lpz = lzi >> 16; + } + lpdest++; + lzi += r_zistepx; + lpz++; + llight += r_lstepx; + lptex += a_ststepxwhole; + lsfrac += a_sstepxfrac; + lptex += lsfrac >> 16; + lsfrac &= 0xFFFF; + ltfrac += a_tstepxfrac; + if (ltfrac & 0x10000) + { + lptex += r_affinetridesc.skinwidth; + ltfrac &= 0xFFFF; + } + } while (--lcount); + } + + pspanpackage++; + } while (pspanpackage->count != -999999); +} + +void R_PolysetDrawSpansConstant8_66( spanpackage_t *pspanpackage) +{ + int lcount; + byte *lpdest; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + { + d_aspancount += ubasestep; + } + + if (lcount) + { + lpdest = pspanpackage->pdest; + lpz = pspanpackage->pz; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) >= *lpz) + { + *lpdest = vid.alphamap[r_aliasblendcolor*256 + *lpdest]; + } + lpdest++; + lzi += r_zistepx; + lpz++; + } while (--lcount); + } + + pspanpackage++; + } while (pspanpackage->count != -999999); +} + +#if !id386 +void R_PolysetDrawSpans8_Opaque (spanpackage_t *pspanpackage) +{ + int lcount; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + { + d_aspancount += ubasestep; + } + + if (lcount) + { + int lsfrac, ltfrac; + byte *lpdest; + byte *lptex; + int llight; + int lzi; + short *lpz; + + lpdest = pspanpackage->pdest; + lptex = pspanpackage->ptex; + lpz = pspanpackage->pz; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + llight = pspanpackage->light; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) >= *lpz) + { +//PGM + /*if(r_newrefdef.rdflags & RDF_IRGOGGLES && RI.currententity->flags & RF_IR_VISIBLE) + *lpdest = ((byte *)vid.colormap)[irtable[*lptex]]; + else*/ + *lpdest = ((byte *)vid.colormap)[*lptex + (llight & 0xFF00)]; +//PGM + *lpz = lzi >> 16; + } + lpdest++; + lzi += r_zistepx; + lpz++; + llight += r_lstepx; + lptex += a_ststepxwhole; + lsfrac += a_sstepxfrac; + lptex += lsfrac >> 16; + lsfrac &= 0xFFFF; + ltfrac += a_tstepxfrac; + if (ltfrac & 0x10000) + { + lptex += r_affinetridesc.skinwidth; + ltfrac &= 0xFFFF; + } + } while (--lcount); + } + + pspanpackage++; + } while (pspanpackage->count != -999999); +} +#endif + +#if 0 +/* +================ +R_PolysetFillSpans8 +================ +*/ +void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) +{ + int color; + +// FIXME: do z buffering + + color = d_aflatcolor++; + + while (1) + { + int lcount; + byte *lpdest; + + lcount = pspanpackage->count; + + if (lcount == -1) + return; + + if (lcount) + { + lpdest = pspanpackage->pdest; + + do + { + *lpdest++ = color; + } while (--lcount); + } + + pspanpackage++; + } +} +#else +void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) +{ + int color; + int lcount; +// FIXME: do z buffering + + color = d_aflatcolor+= 100; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + { + d_aspancount += ubasestep; + } + + if (lcount) + { + int lsfrac, ltfrac; + pixel_t *lpdest; + byte *lptex; + int llight; + int lzi; + short *lpz; + + lpdest = pspanpackage->pdest; + lptex = pspanpackage->ptex; + lpz = pspanpackage->pz; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + llight = pspanpackage->light; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) >= *lpz) + { +//PGM + /*if(r_newrefdef.rdflags & RDF_IRGOGGLES && RI.currententity->flags & RF_IR_VISIBLE) + *lpdest = ((byte *)vid.colormap)[irtable[*lptex]]; + else*/ + *lpdest = color; //((byte *)vid.colormap)[*lptex + (llight & 0xFF00)]; +//PGM + *lpz = lzi >> 16; + } + lpdest++; + lzi += r_zistepx; + lpz++; + llight += r_lstepx; + lptex += a_ststepxwhole; + lsfrac += a_sstepxfrac; + lptex += lsfrac >> 16; + lsfrac &= 0xFFFF; + ltfrac += a_tstepxfrac; + if (ltfrac & 0x10000) + { + lptex += r_affinetridesc.skinwidth; + ltfrac &= 0xFFFF; + } + } while (--lcount); + } + + pspanpackage++; + } while (pspanpackage->count != -999999); +} +#endif +/* +================ +R_RasterizeAliasPolySmooth +================ +*/ +void R_RasterizeAliasPolySmooth (void) +{ + int initialleftheight, initialrightheight; + int *plefttop, *prighttop, *pleftbottom, *prightbottom; + int working_lstepx, originalcount; + + plefttop = pedgetable->pleftedgevert0; + prighttop = pedgetable->prightedgevert0; + + pleftbottom = pedgetable->pleftedgevert1; + prightbottom = pedgetable->prightedgevert1; + + initialleftheight = pleftbottom[1] - plefttop[1]; + initialrightheight = prightbottom[1] - prighttop[1]; + +// +// set the s, t, and light gradients, which are consistent across the triangle +// because being a triangle, things are affine +// + R_PolysetCalcGradients (r_affinetridesc.skinwidth); +// +// rasterize the polygon +// + +// +// scan out the top (and possibly only) part of the left edge +// + d_pedgespanpackage = a_spans; + + ystart = plefttop[1]; + d_aspancount = plefttop[0] - prighttop[0]; + + d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) + + (plefttop[3] >> 16) * r_affinetridesc.skinwidth; +//#if id386ALIAS +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + d_sfrac = (plefttop[2] & 0xFFFF) << 16; + d_tfrac = (plefttop[3] & 0xFFFF) << 16; + } +//#else + else +#endif + { + d_sfrac = plefttop[2] & 0xFFFF; + d_tfrac = plefttop[3] & 0xFFFF; + } +//#endif + d_light = plefttop[4]; + d_zi = plefttop[5]; + + d_pdest = (pixel_t *)d_viewbuffer + + ystart * r_screenwidth + plefttop[0]; + d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; + + if (initialleftheight == 1) + { + d_pedgespanpackage->pdest = d_pdest; + d_pedgespanpackage->pz = d_pz; + d_pedgespanpackage->count = d_aspancount; + d_pedgespanpackage->ptex = d_ptex; + + d_pedgespanpackage->sfrac = d_sfrac; + d_pedgespanpackage->tfrac = d_tfrac; + + // FIXME: need to clamp l, s, t, at both ends? + d_pedgespanpackage->light = d_light; + d_pedgespanpackage->zi = d_zi; + + d_pedgespanpackage++; + } + else + { + R_PolysetSetUpForLineScan(plefttop[0], plefttop[1], + pleftbottom[0], pleftbottom[1]); + +//#if id386ALIAS +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + d_pzbasestep = (d_zwidth + ubasestep) << 1; + d_pzextrastep = d_pzbasestep + 2; + } +//#else + else +#endif + { + d_pzbasestep = d_zwidth + ubasestep; + d_pzextrastep = d_pzbasestep + 1; + } +//#endif + + d_pdestbasestep = r_screenwidth + ubasestep; + d_pdestextrastep = d_pdestbasestep + 1; + + // TODO: can reuse partial expressions here + + // for negative steps in x along left edge, bias toward overflow rather than + // underflow (sort of turning the floor () we did in the gradient calcs into + // ceil (), but plus a little bit) + if (ubasestep < 0) + working_lstepx = r_lstepx - 1; + else + working_lstepx = r_lstepx; + + d_countextrastep = ubasestep + 1; + d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) + + ((r_tstepy + r_tstepx * ubasestep) >> 16) * + r_affinetridesc.skinwidth; +//#if id386ALIAS +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16; + d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16; + } + else +#endif + { +//#else + d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF; + d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF; + } +//#endif + d_lightbasestep = r_lstepy + working_lstepx * ubasestep; + d_zibasestep = r_zistepy + r_zistepx * ubasestep; + + d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) + + ((r_tstepy + r_tstepx * d_countextrastep) >> 16) * + r_affinetridesc.skinwidth; +//#if id386ALIAS +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) << 16; + d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) << 16; + } + else +#endif + { +//#else + d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) & 0xFFFF; + d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) & 0xFFFF; + } +//#endif + d_lightextrastep = d_lightbasestep + working_lstepx; + d_ziextrastep = d_zibasestep + r_zistepx; + +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + R_PolysetScanLeftEdge (initialleftheight); + } + else +#endif + { + R_PolysetScanLeftEdge_C(initialleftheight); + } + } + +// +// scan out the bottom part of the left edge, if it exists +// + if (pedgetable->numleftedges == 2) + { + int height; + + plefttop = pleftbottom; + pleftbottom = pedgetable->pleftedgevert2; + + height = pleftbottom[1] - plefttop[1]; + +// TODO: make this a function; modularize this function in general + + ystart = plefttop[1]; + d_aspancount = plefttop[0] - prighttop[0]; + d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) + + (plefttop[3] >> 16) * r_affinetridesc.skinwidth; + d_sfrac = 0; + d_tfrac = 0; + d_light = plefttop[4]; + d_zi = plefttop[5]; + + d_pdest = (pixel_t *)d_viewbuffer + ystart * r_screenwidth + plefttop[0]; + d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; + + if (height == 1) + { + d_pedgespanpackage->pdest = d_pdest; + d_pedgespanpackage->pz = d_pz; + d_pedgespanpackage->count = d_aspancount; + d_pedgespanpackage->ptex = d_ptex; + + d_pedgespanpackage->sfrac = d_sfrac; + d_pedgespanpackage->tfrac = d_tfrac; + + // FIXME: need to clamp l, s, t, at both ends? + d_pedgespanpackage->light = d_light; + d_pedgespanpackage->zi = d_zi; + + d_pedgespanpackage++; + } + else + { + R_PolysetSetUpForLineScan(plefttop[0], plefttop[1], + pleftbottom[0], pleftbottom[1]); + + d_pdestbasestep = r_screenwidth + ubasestep; + d_pdestextrastep = d_pdestbasestep + 1; + +//#if id386ALIAS +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + d_pzbasestep = (d_zwidth + ubasestep) << 1; + d_pzextrastep = d_pzbasestep + 2; + } +//#else + else +#endif + { + d_pzbasestep = d_zwidth + ubasestep; + d_pzextrastep = d_pzbasestep + 1; + } +//#endif + + if (ubasestep < 0) + working_lstepx = r_lstepx - 1; + else + working_lstepx = r_lstepx; + + d_countextrastep = ubasestep + 1; + d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) + + ((r_tstepy + r_tstepx * ubasestep) >> 16) * + r_affinetridesc.skinwidth; +//#if id386ALIAS +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16; + d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16; + } +//#else + else +#endif + { + d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF; + d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF; + } +//#endif + d_lightbasestep = r_lstepy + working_lstepx * ubasestep; + d_zibasestep = r_zistepy + r_zistepx * ubasestep; + + d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) + + ((r_tstepy + r_tstepx * d_countextrastep) >> 16) * + r_affinetridesc.skinwidth; +//#if id386ALIAS +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + d_sfracextrastep = ((r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF)<<16; + d_tfracextrastep = ((r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF)<<16; + } + else +#endif +//#endif + { + d_sfracextrastep = (r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF; + d_tfracextrastep = (r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF; + } +//#endif + d_lightextrastep = d_lightbasestep + working_lstepx; + d_ziextrastep = d_zibasestep + r_zistepx; + +#if id386 + if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) + { + R_PolysetScanLeftEdge (height); + } + else +#endif + { + R_PolysetScanLeftEdge_C(height); + } + } + } + +// scan out the top (and possibly only) part of the right edge, updating the +// count field + d_pedgespanpackage = a_spans; + + R_PolysetSetUpForLineScan(prighttop[0], prighttop[1], + prightbottom[0], prightbottom[1]); + d_aspancount = 0; + d_countextrastep = ubasestep + 1; + originalcount = a_spans[initialrightheight].count; + a_spans[initialrightheight].count = -999999; // mark end of the spanpackages + (*d_pdrawspans) (a_spans); + +// scan out the bottom part of the right edge, if it exists + if (pedgetable->numrightedges == 2) + { + int height; + spanpackage_t *pstart; + + pstart = a_spans + initialrightheight; + pstart->count = originalcount; + + d_aspancount = prightbottom[0] - prighttop[0]; + + prighttop = prightbottom; + prightbottom = pedgetable->prightedgevert2; + + height = prightbottom[1] - prighttop[1]; + + R_PolysetSetUpForLineScan(prighttop[0], prighttop[1], + prightbottom[0], prightbottom[1]); + + d_countextrastep = ubasestep + 1; + a_spans[initialrightheight + height].count = -999999; + // mark end of the spanpackages + (*d_pdrawspans) (pstart); + } +} + + +/* +================ +R_PolysetSetEdgeTable +================ +*/ +void R_PolysetSetEdgeTable (void) +{ + int edgetableindex; + + edgetableindex = 0; // assume the vertices are already in + // top to bottom order + +// +// determine which edges are right & left, and the order in which +// to rasterize them +// + if (r_p0[1] >= r_p1[1]) + { + if (r_p0[1] == r_p1[1]) + { + if (r_p0[1] < r_p2[1]) + pedgetable = &edgetables[2]; + else + pedgetable = &edgetables[5]; + + return; + } + else + { + edgetableindex = 1; + } + } + + if (r_p0[1] == r_p2[1]) + { + if (edgetableindex) + pedgetable = &edgetables[8]; + else + pedgetable = &edgetables[9]; + + return; + } + else if (r_p1[1] == r_p2[1]) + { + if (edgetableindex) + pedgetable = &edgetables[10]; + else + pedgetable = &edgetables[11]; + + return; + } + + if (r_p0[1] > r_p2[1]) + edgetableindex += 2; + + if (r_p1[1] > r_p2[1]) + edgetableindex += 4; + + pedgetable = &edgetables[edgetableindex]; +} + + diff --git a/r_trialias.c b/r_trialias.c new file mode 100644 index 00000000..5616da31 --- /dev/null +++ b/r_trialias.c @@ -0,0 +1,229 @@ +#include "r_local.h" + +// not really draw alias models here, but use this to draw triangles + +int r_amodels_drawn; + +affinetridesc_t r_affinetridesc; + +vec3_t r_plightvec; +vec3_t r_lerped[1024]; +vec3_t r_lerp_frontv, r_lerp_backv, r_lerp_move; + +int r_ambientlight; +int r_aliasblendcolor; +float r_shadelight; + + +float aliastransform[3][4]; +float aliasworldtransform[3][4]; +float aliasoldworldtransform[3][4]; + +static float s_ziscale; +static vec3_t s_alias_forward, s_alias_right, s_alias_up; + + +#define NUMVERTEXNORMALS 162 + +float r_avertexnormals[NUMVERTEXNORMALS][3] = { +#include "anorms.h" +}; + + +void R_AliasSetUpTransform (void); +void R_AliasTransformVector (vec3_t in, vec3_t out, float m[3][4] ); +void R_AliasProjectAndClipTestFinalVert (finalvert_t *fv); + +void R_AliasTransformFinalVerts( int numpoints, finalvert_t *fv, dtrivertx_t *oldv, dtrivertx_t *newv ); + + +/* +================ +R_AliasCheckBBox +================ +*/ +typedef struct { + int index0; + int index1; +} aedge_t; + +static aedge_t aedges[12] = { +{0, 1}, {1, 2}, {2, 3}, {3, 0}, +{4, 5}, {5, 6}, {6, 7}, {7, 4}, +{0, 5}, {1, 4}, {2, 7}, {3, 6} +}; + +#define BBOX_TRIVIAL_ACCEPT 0 +#define BBOX_MUST_CLIP_XY 1 +#define BBOX_MUST_CLIP_Z 2 +#define BBOX_TRIVIAL_REJECT 8 + + +/* +================ +R_AliasTransformVector +================ +*/ +void R_AliasTransformVector(vec3_t in, vec3_t out, float xf[3][4] ) +{ + out[0] = DotProduct(in, xf[0]) + xf[0][3]; + out[1] = DotProduct(in, xf[1]) + xf[1][3]; + out[2] = DotProduct(in, xf[2]) + xf[2][3]; +} + +void VectorInverse (vec3_t v) +{ + v[0] = -v[0]; + v[1] = -v[1]; + v[2] = -v[2]; +} + +/* +================ +R_AliasSetUpTransform +================ +*/ +void R_AliasSetUpTransform (void) +{ + int i; + static float viewmatrix[3][4]; + vec3_t angles; + +// TODO: should really be stored with the entity instead of being reconstructed +// TODO: should use a look-up table +// TODO: could cache lazily, stored in the entity +// + + s_ziscale = (float)0x8000 * (float)0x10000; + angles[ROLL] = RI.currententity->angles[ROLL]; + angles[PITCH] = RI.currententity->angles[PITCH]; + angles[YAW] = RI.currententity->angles[YAW]; + AngleVectors( angles, s_alias_forward, s_alias_right, s_alias_up ); + +// TODO: can do this with simple matrix rearrangement + + memset( aliasworldtransform, 0, sizeof( aliasworldtransform ) ); + memset( aliasoldworldtransform, 0, sizeof( aliasworldtransform ) ); + + for (i=0 ; i<3 ; i++) + { + aliasoldworldtransform[i][0] = aliasworldtransform[i][0] = s_alias_forward[i]; + aliasoldworldtransform[i][0] = aliasworldtransform[i][1] = -s_alias_right[i]; + aliasoldworldtransform[i][0] = aliasworldtransform[i][2] = s_alias_up[i]; + } + + aliasworldtransform[0][3] = RI.currententity->origin[0]-r_origin[0]; + aliasworldtransform[1][3] = RI.currententity->origin[1]-r_origin[1]; + aliasworldtransform[2][3] = RI.currententity->origin[2]-r_origin[2]; + + //aliasoldworldtransform[0][3] = RI.currententity->oldorigin[0]-r_origin[0]; + //aliasoldworldtransform[1][3] = RI.currententity->oldorigin[1]-r_origin[1]; + //aliasoldworldtransform[2][3] = RI.currententity->oldorigin[2]-r_origin[2]; + +// FIXME: can do more efficiently than full concatenation +// memcpy( rotationmatrix, t2matrix, sizeof( rotationmatrix ) ); + +// R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix); + +// TODO: should be global, set when vright, etc., set + VectorCopy (vright, viewmatrix[0]); + VectorCopy (vup, viewmatrix[1]); + VectorInverse (viewmatrix[1]); + //VectorScale(viewmatrix[1], -1, viewmatrix[1]); + VectorCopy (vpn, viewmatrix[2]); + + viewmatrix[0][3] = 0; + viewmatrix[1][3] = 0; + viewmatrix[2][3] = 0; + +// memcpy( aliasworldtransform, rotationmatrix, sizeof( aliastransform ) ); + + R_ConcatTransforms (viewmatrix, aliasworldtransform, aliastransform); + + aliasworldtransform[0][3] = RI.currententity->origin[0]; + aliasworldtransform[1][3] = RI.currententity->origin[1]; + aliasworldtransform[2][3] = RI.currententity->origin[2]; + + //aliasoldworldtransform[0][3] = RI.currententity->oldorigin[0]; + //aliasoldworldtransform[1][3] = RI.currententity->oldorigin[1]; + //aliasoldworldtransform[2][3] = RI.currententity->oldorigin[2]; +} + +/* +================ +R_AliasProjectAndClipTestFinalVert +================ +*/ +void R_AliasProjectAndClipTestFinalVert( finalvert_t *fv ) +{ + float zi; + float x, y, z; + + // project points + x = fv->xyz[0]; + y = fv->xyz[1]; + z = fv->xyz[2]; + zi = 1.0 / z; + + fv->zi = zi * s_ziscale; + + fv->u = (x * aliasxscale * zi) + aliasxcenter; + fv->v = (y * aliasyscale * zi) + aliasycenter; + + if (fv->u < RI.aliasvrect.x) + fv->flags |= ALIAS_LEFT_CLIP; + if (fv->v < RI.aliasvrect.y) + fv->flags |= ALIAS_TOP_CLIP; + if (fv->u > RI.aliasvrectright) + fv->flags |= ALIAS_RIGHT_CLIP; + if (fv->v > RI.aliasvrectbottom) + fv->flags |= ALIAS_BOTTOM_CLIP; +} + +void R_SetupFinalVert( finalvert_t *fv, float x, float y, float z, int light, int s, int t ) +{ + vec3_t v = {x, y, z}; + + fv->xyz[0] = DotProduct(v, aliastransform[0]) + aliastransform[0][3]; + fv->xyz[1] = DotProduct(v, aliastransform[1]) + aliastransform[1][3]; + fv->xyz[2] = DotProduct(v, aliastransform[2]) + aliastransform[2][3]; + + fv->flags = 0; + + fv->l = light; + + if ( fv->xyz[2] < ALIAS_Z_CLIP_PLANE ) + { + fv->flags |= ALIAS_Z_CLIP; + } + else + { + R_AliasProjectAndClipTestFinalVert( fv ); + } + + fv->s = s << 16; + fv->t = t << 16; +} + +void R_RenderTriangle( finalvert_t *pfv ) +{ + + if ( pfv[0].flags & pfv[1].flags & pfv[2].flags ) + return ; // completely clipped + + if ( ! (pfv[0].flags | pfv[1].flags | pfv[2].flags) ) + { // totally unclipped + aliastriangleparms.a = &pfv[0]; + aliastriangleparms.b = &pfv[1]; + aliastriangleparms.c = &pfv[2]; + + R_DrawTriangle(); + } + else + { // partially clipped + R_AliasClipTriangle (&pfv[0], &pfv[1], &pfv[2]); + } +} + + + From 870ae030cad8e118cf48bc6e17f3462e4ab120d8 Mon Sep 17 00:00:00 2001 From: mittorn Date: Tue, 26 Mar 2019 05:53:00 +0700 Subject: [PATCH 025/115] ref_soft: Simple triapi and studio rendering (flat fill only) --- r_context.c | 24 - r_local.h | 14 +- r_main.c | 27 +- r_polyse.c | 2 +- r_studio.c | 3761 +++++++++++++++++++++++++++++++++++++++++++++++++++ r_triapi.c | 43 +- 6 files changed, 3834 insertions(+), 37 deletions(-) create mode 100644 r_studio.c diff --git a/r_context.c b/r_context.c index 75158b3c..6291680b 100644 --- a/r_context.c +++ b/r_context.c @@ -407,20 +407,6 @@ void R_ClearAllDecals() } -float R_StudioEstimateFrame(cl_entity_t *e, mstudioseqdesc_t *pseqdesc) -{ - return 0; -} - -void R_StudioLerpMovement(cl_entity_t *e, double time, vec3_t origin, vec3_t angles) -{ - -} - -void CL_InitStudioAPI() -{ - -} void R_InitSkyClouds(mip_t *mt, texture_t *tx, qboolean custom_palette) { @@ -437,11 +423,6 @@ void Mod_LoadMapSprite(model_t *mod, const void *buffer, size_t size, qboolean * } -void Mod_StudioLoadTextures(model_t *mod, void *data) -{ - -} - void CL_DrawParticles(double frametime, particle_t *cl_active_particles, float partsize) { @@ -512,11 +493,6 @@ void CL_DrawParticlesExternal(const ref_viewpass_t *rvp, qboolean trans_pass, fl // no renderapi support } -struct mstudiotex_s *R_StudioGetTexture(cl_entity_t *e) -{ - return NULL; -} - void GL_BuildLightmaps() { diff --git a/r_local.h b/r_local.h index dbd5ff9d..2e6f296c 100644 --- a/r_local.h +++ b/r_local.h @@ -84,7 +84,7 @@ extern byte *r_temppool; #define RP_LOCALCLIENT( e ) ((e) != NULL && (e)->index == gEngfuncs.GetPlayerIndex() && e->player ) #define RP_NORMALPASS() ( FBitSet( RI.params, RP_NONVIEWERREF ) == 0 ) -#define CL_IsViewEntityLocalPlayer() ( gEngfuncs.GetViewEntIndex() == gEngfuncs.GetPlayerIndex() ) +#define CL_IsViewEntityLocalPlayer() ( ENGINE_GET_PARM( PARM_VIEWENT_INDEX ) == ENGINE_GET_PARM( PARM_PLAYER_INDEX ) ) #define CULL_VISIBLE 0 // not culled #define CULL_BACKSIDE 1 // backside of transparent wall @@ -547,7 +547,7 @@ void R_SpriteInit( void ); void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags ); mspriteframe_t *R_GetSpriteFrame( const model_t *pModel, int frame, float yaw ); void R_DrawSpriteModel( cl_entity_t *e ); - +#endif // // gl_studio.c // @@ -567,7 +567,7 @@ void R_StudioResetPlayerModels( void ); void CL_InitStudioAPI( void ); void Mod_StudioLoadTextures( model_t *mod, void *data ); void Mod_StudioUnloadTextures( void *data ); - +#if 0 // // gl_alias.c // @@ -682,7 +682,7 @@ void TriFog( float flFogColor[3], float flStart, float flEnd, int bOn ); void TriGetMatrix( const int pname, float *matrix ); void TriFogParams( float flDensity, int iFogSkybox ); void TriCullFace( TRICULLSTYLE mode ); - +void TriBrightness( float brightness ); #define ENGINE_GET_PARM_ (*gEngfuncs.EngineGetParm) #define ENGINE_GET_PARM( parm ) ENGINE_GET_PARM_( (parm), 0 ) @@ -694,6 +694,12 @@ extern cvar_t *r_drawentities; extern cvar_t *vid_brightness; extern cvar_t *vid_gamma; extern cvar_t *r_norefresh; +extern cvar_t *r_dynamic; +extern cvar_t *r_lightmap; + +// todo: gl_cull.c +#define R_CullModel(...) 0 + #if 0 // // renderer cvars diff --git a/r_main.c b/r_main.c index 34c35cf6..f3f0ad9d 100644 --- a/r_main.c +++ b/r_main.c @@ -91,6 +91,8 @@ cvar_t *r_dspeeds; cvar_t *r_fullbright; cvar_t *r_lerpmodels; cvar_t *r_novis; +cvar_t *r_lightmap; +cvar_t *r_dynamic; cvar_t *r_speeds; cvar_t *r_lightlevel; //FIXME HACK @@ -207,7 +209,7 @@ static int R_RankForRenderMode( int rendermode ) } return 0; } - +#if 0 /* ================ R_GetEntityRenderMode @@ -227,7 +229,7 @@ int R_GetEntityRenderMode( cl_entity_t *ent ) RI.currententity = ent; return ent->curstate.rendermode; } - +#endif void R_AllowFog( qboolean allowed ) { @@ -1002,15 +1004,23 @@ R_DrawEntitiesOnList void R_DrawEntitiesOnList( void ) { int i; - + extern int d_aflatcolor; + d_aflatcolor = 0; tr.blend = 1.0f; // GL_CheckForErrors(); - + // HACK: setup world transform + void R_AliasSetUpTransform (void); + RI.currententity = gEngfuncs.GetEntityByIndex(0); + R_AliasSetUpTransform(); + extern void (*d_pdrawspans)(void *); + extern void R_PolysetFillSpans8 ( void * ); + d_pdrawspans = R_PolysetFillSpans8; // first draw solid entities for( i = 0; i < tr.draw_list->num_solid_entities && !RI.onlyClientDraw; i++ ) { RI.currententity = tr.draw_list->solid_entities[i]; RI.currentmodel = RI.currententity->model; + d_aflatcolor += 500; Assert( RI.currententity != NULL ); Assert( RI.currentmodel != NULL ); @@ -1025,7 +1035,7 @@ void R_DrawEntitiesOnList( void ) break; case mod_studio: //R_DrawStudioModel( RI.currententity ); - {finalvert_t fv[3]; + /*{finalvert_t fv[3]; void R_AliasSetUpTransform (void); extern void (*d_pdrawspans)(void *); extern void R_PolysetFillSpans8 ( void * ); @@ -1036,7 +1046,8 @@ void R_DrawEntitiesOnList( void ) R_SetupFinalVert( &fv[1], -10, 10, 10, 0, 0, 0); R_SetupFinalVert( &fv[2], 10, 10, -10, 0, 0, 0); R_RenderTriangle( &fv ); - } + }*/ + R_DrawStudioModel( RI.currententity ); break; default: @@ -1868,6 +1879,9 @@ qboolean R_Init() r_fullbright = gEngfuncs.Cvar_Get( "r_fullbright", "0", FCVAR_CHEAT, "disable lightmaps, get fullbright for entities" ); sw_mipcap = gEngfuncs.Cvar_Get( "r_fullbright", "0", FCVAR_CHEAT, "disable lightmaps, get fullbright for entities" ); + r_dynamic = gEngfuncs.Cvar_Get( "r_dynamic", "1", FCVAR_ARCHIVE, "allow dynamic lighting (dlights, lightstyles)" ); + r_lightmap = gEngfuncs.Cvar_Get( "r_lightmap", "0", FCVAR_CHEAT, "lightmap debugging tool" ); + // sw_aliasstats = ri.Cvar_Get ("sw_polymodelstats", "0", 0); // sw_allow_modex = ri.Cvar_Get( "sw_allow_modex", "1", CVAR_ARCHIVE ); sw_clearcolor = gEngfuncs.Cvar_Get ("sw_clearcolor", "2", 0, "screen clear color"); @@ -1915,6 +1929,7 @@ qboolean R_Init() view_clipplanes[1].rightedge = true; view_clipplanes[1].leftedge = view_clipplanes[2].leftedge =view_clipplanes[3].leftedge = false; view_clipplanes[0].rightedge = view_clipplanes[2].rightedge = view_clipplanes[3].rightedge = false; + R_StudioInit(); return true; } diff --git a/r_polyse.c b/r_polyse.c index fed994a0..c71e82d4 100644 --- a/r_polyse.c +++ b/r_polyse.c @@ -1149,7 +1149,7 @@ void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) int lcount; // FIXME: do z buffering - color = d_aflatcolor+= 100; + color = d_aflatcolor++ * 10; do { diff --git a/r_studio.c b/r_studio.c new file mode 100644 index 00000000..29974842 --- /dev/null +++ b/r_studio.c @@ -0,0 +1,3761 @@ +/* +gl_studio.c - studio model renderer +Copyright (C) 2010 Uncle Mike + +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 3 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. +*/ + +#include "r_local.h" +#include "mathlib.h" +#include "const.h" +#include "r_studioint.h" +#include "triangleapi.h" +#include "studio.h" +#include "pm_local.h" +//#include "cl_tent.h" +//#include "client.h" +#include "pmtrace.h" + +#define EVENT_CLIENT 5000 // less than this value it's a server-side studio events +#define MAX_LOCALLIGHTS 4 + +typedef struct +{ + char name[MAX_OSPATH]; + char modelname[MAX_OSPATH]; + model_t *model; +} player_model_t; + +cvar_t *r_glowshellfreq; + +cvar_t r_shadows = { "r_shadows", "0", 0 }; + +static vec3_t hullcolor[8] = +{ +{ 1.0f, 1.0f, 1.0f }, +{ 1.0f, 0.5f, 0.5f }, +{ 0.5f, 1.0f, 0.5f }, +{ 1.0f, 1.0f, 0.5f }, +{ 0.5f, 0.5f, 1.0f }, +{ 1.0f, 0.5f, 1.0f }, +{ 0.5f, 1.0f, 1.0f }, +{ 1.0f, 1.0f, 1.0f }, +}; + +typedef struct sortedmesh_s +{ + mstudiomesh_t *mesh; + int flags; // face flags +} sortedmesh_t; + +typedef struct +{ + double time; + double frametime; + int framecount; // studio framecount + qboolean interpolate; + int rendermode; + float blend; // blend value + + // bones + matrix3x4 rotationmatrix; + matrix3x4 bonestransform[MAXSTUDIOBONES]; + matrix3x4 lighttransform[MAXSTUDIOBONES]; + + // boneweighting stuff + matrix3x4 worldtransform[MAXSTUDIOBONES]; + + // cached bones + matrix3x4 cached_bonestransform[MAXSTUDIOBONES]; + matrix3x4 cached_lighttransform[MAXSTUDIOBONES]; + char cached_bonenames[MAXSTUDIOBONES][32]; + int cached_numbones; // number of bones in cache + + sortedmesh_t meshes[MAXSTUDIOMESHES]; // sorted meshes + vec3_t verts[MAXSTUDIOVERTS]; + vec3_t norms[MAXSTUDIOVERTS]; + + // lighting state + float ambientlight; + float shadelight; + vec3_t lightvec; // averaging light direction + vec3_t lightspot; // shadow spot + vec3_t lightcolor; // averaging lightcolor + vec3_t blightvec[MAXSTUDIOBONES]; // bone light vecs + vec3_t lightvalues[MAXSTUDIOVERTS]; // precomputed lightvalues per each shared vertex of submodel + + // chrome stuff + vec3_t chrome_origin; + vec2_t chrome[MAXSTUDIOVERTS]; // texture coords for surface normals + vec3_t chromeright[MAXSTUDIOBONES]; // chrome vector "right" in bone reference frames + vec3_t chromeup[MAXSTUDIOBONES]; // chrome vector "up" in bone reference frames + int chromeage[MAXSTUDIOBONES]; // last time chrome vectors were updated + + // glowshell stuff + int normaltable[MAXSTUDIOVERTS]; // glowshell uses this + + // elights cache + int numlocallights; + int lightage[MAXSTUDIOBONES]; + dlight_t *locallight[MAX_LOCALLIGHTS]; + color24 locallightcolor[MAX_LOCALLIGHTS]; + vec4_t lightpos[MAXSTUDIOVERTS][MAX_LOCALLIGHTS]; + vec3_t lightbonepos[MAXSTUDIOBONES][MAX_LOCALLIGHTS]; + float locallightR2[MAX_LOCALLIGHTS]; + + // playermodels + player_model_t player_models[MAX_CLIENTS]; +} studio_draw_state_t; + +// studio-related cvars +static cvar_t *r_studio_sort_textures; +static cvar_t *r_drawviewmodel; +cvar_t *cl_righthand = NULL; +static cvar_t *cl_himodels; +static cvar_t *r_studio_drawelements; + +static r_studio_interface_t *pStudioDraw; +static studio_draw_state_t g_studio; // global studio state + +// global variables +static qboolean m_fDoRemap; +mstudiomodel_t *m_pSubModel; +mstudiobodyparts_t *m_pBodyPart; +player_info_t *m_pPlayerInfo; +studiohdr_t *m_pStudioHeader; +float m_flGaitMovement; +int g_iBackFaceCull; +int g_nTopColor, g_nBottomColor; // remap colors +int g_nFaceFlags, g_nForceFaceFlags; + +/* +==================== +R_StudioInit + +==================== +*/ +void R_StudioInit( void ) +{ + cl_himodels = gEngfuncs.Cvar_Get( "cl_himodels", "1", FCVAR_ARCHIVE, "draw high-resolution player models in multiplayer" ); + r_studio_sort_textures = gEngfuncs.Cvar_Get( "r_studio_sort_textures", "0", FCVAR_ARCHIVE, "change draw order for additive meshes" ); + r_drawviewmodel = gEngfuncs.Cvar_Get( "r_drawviewmodel", "1", 0, "draw firstperson weapon model" ); + r_studio_drawelements = gEngfuncs.Cvar_Get( "r_studio_drawelements", "1", FCVAR_ARCHIVE, "use glDrawElements for studiomodels" ); + + Matrix3x4_LoadIdentity( g_studio.rotationmatrix ); + r_glowshellfreq = gEngfuncs.Cvar_Get( "r_glowshellfreq", "2.2", 0, "glowing shell frequency update" ); + + // g-cont. cvar disabled by Valve +// gEngfuncs.Cvar_RegisterVariable( &r_shadows ); + + g_studio.interpolate = true; + g_studio.framecount = 0; + m_fDoRemap = false; +} + +/* +================ +R_StudioSetupTimings + +init current time for a given model +================ +*/ +static void R_StudioSetupTimings( void ) +{ + if( RI.drawWorld ) + { + // synchronize with server time + g_studio.time = gpGlobals->time; + g_studio.frametime = gpGlobals->time - gpGlobals->oldtime; + } + else + { + // menu stuff + g_studio.time = gpGlobals->realtime; + g_studio.frametime = gpGlobals->frametime; + } +} + +/* +================ +R_AllowFlipViewModel + +should a flip the viewmodel if cl_righthand is set to 1 +================ +*/ +static qboolean R_AllowFlipViewModel( cl_entity_t *e ) +{ + if( cl_righthand && cl_righthand->value > 0 ) + { + if( e == gEngfuncs.GetViewModel() ) + return true; + } + + return false; +} + +/* +================ +R_StudioComputeBBox + +Compute a full bounding box for current sequence +================ +*/ +static qboolean R_StudioComputeBBox( vec3_t bbox[8] ) +{ + vec3_t studio_mins, studio_maxs; + vec3_t mins, maxs, p1, p2; + cl_entity_t *e = RI.currententity; + mstudioseqdesc_t *pseqdesc; + int i; + + if( !m_pStudioHeader ) + return false; + + // check if we have valid mins\maxs + if( !VectorCompare( vec3_origin, RI.currentmodel->mins )) + { + // clipping bounding box + VectorCopy( RI.currentmodel->mins, mins ); + VectorCopy( RI.currentmodel->maxs, maxs ); + } + else + { + ClearBounds( mins, maxs ); + } + + // check sequence range + if( e->curstate.sequence < 0 || e->curstate.sequence >= m_pStudioHeader->numseq ) + e->curstate.sequence = 0; + + pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + e->curstate.sequence; + + // add sequence box to the model box + AddPointToBounds( pseqdesc->bbmin, mins, maxs ); + AddPointToBounds( pseqdesc->bbmax, mins, maxs ); + ClearBounds( studio_mins, studio_maxs ); + + // compute a full bounding box + for( i = 0; i < 8; i++ ) + { + p1[0] = ( i & 1 ) ? mins[0] : maxs[0]; + p1[1] = ( i & 2 ) ? mins[1] : maxs[1]; + p1[2] = ( i & 4 ) ? mins[2] : maxs[2]; + + Matrix3x4_VectorTransform( g_studio.rotationmatrix, p1, p2 ); + AddPointToBounds( p2, studio_mins, studio_maxs ); + if( bbox ) VectorCopy( p2, bbox[i] ); + } + + if( !bbox && R_CullModel( e, studio_mins, studio_maxs )) + return false; // model culled + return true; // visible +} + +void R_StudioComputeSkinMatrix( mstudioboneweight_t *boneweights, matrix3x4 result ) +{ + float flWeight0, flWeight1, flWeight2, flWeight3; + int i, numbones = 0; + float flTotal; + + for( i = 0; i < MAXSTUDIOBONEWEIGHTS; i++ ) + { + if( boneweights->bone[i] != -1 ) + numbones++; + } + + if( numbones == 4 ) + { + vec4_t *boneMat0 = (vec4_t *)g_studio.worldtransform[boneweights->bone[0]]; + vec4_t *boneMat1 = (vec4_t *)g_studio.worldtransform[boneweights->bone[1]]; + vec4_t *boneMat2 = (vec4_t *)g_studio.worldtransform[boneweights->bone[2]]; + vec4_t *boneMat3 = (vec4_t *)g_studio.worldtransform[boneweights->bone[3]]; + flWeight0 = boneweights->weight[0] / 255.0f; + flWeight1 = boneweights->weight[1] / 255.0f; + flWeight2 = boneweights->weight[2] / 255.0f; + flWeight3 = boneweights->weight[3] / 255.0f; + flTotal = flWeight0 + flWeight1 + flWeight2 + flWeight3; + + if( flTotal < 1.0f ) flWeight0 += 1.0f - flTotal; // compensate rounding error + + result[0][0] = boneMat0[0][0] * flWeight0 + boneMat1[0][0] * flWeight1 + boneMat2[0][0] * flWeight2 + boneMat3[0][0] * flWeight3; + result[0][1] = boneMat0[0][1] * flWeight0 + boneMat1[0][1] * flWeight1 + boneMat2[0][1] * flWeight2 + boneMat3[0][1] * flWeight3; + result[0][2] = boneMat0[0][2] * flWeight0 + boneMat1[0][2] * flWeight1 + boneMat2[0][2] * flWeight2 + boneMat3[0][2] * flWeight3; + result[0][3] = boneMat0[0][3] * flWeight0 + boneMat1[0][3] * flWeight1 + boneMat2[0][3] * flWeight2 + boneMat3[0][3] * flWeight3; + result[1][0] = boneMat0[1][0] * flWeight0 + boneMat1[1][0] * flWeight1 + boneMat2[1][0] * flWeight2 + boneMat3[1][0] * flWeight3; + result[1][1] = boneMat0[1][1] * flWeight0 + boneMat1[1][1] * flWeight1 + boneMat2[1][1] * flWeight2 + boneMat3[1][1] * flWeight3; + result[1][2] = boneMat0[1][2] * flWeight0 + boneMat1[1][2] * flWeight1 + boneMat2[1][2] * flWeight2 + boneMat3[1][2] * flWeight3; + result[1][3] = boneMat0[1][3] * flWeight0 + boneMat1[1][3] * flWeight1 + boneMat2[1][3] * flWeight2 + boneMat3[1][3] * flWeight3; + result[2][0] = boneMat0[2][0] * flWeight0 + boneMat1[2][0] * flWeight1 + boneMat2[2][0] * flWeight2 + boneMat3[2][0] * flWeight3; + result[2][1] = boneMat0[2][1] * flWeight0 + boneMat1[2][1] * flWeight1 + boneMat2[2][1] * flWeight2 + boneMat3[2][1] * flWeight3; + result[2][2] = boneMat0[2][2] * flWeight0 + boneMat1[2][2] * flWeight1 + boneMat2[2][2] * flWeight2 + boneMat3[2][2] * flWeight3; + result[2][3] = boneMat0[2][3] * flWeight0 + boneMat1[2][3] * flWeight1 + boneMat2[2][3] * flWeight2 + boneMat3[2][3] * flWeight3; + } + else if( numbones == 3 ) + { + vec4_t *boneMat0 = (vec4_t *)g_studio.worldtransform[boneweights->bone[0]]; + vec4_t *boneMat1 = (vec4_t *)g_studio.worldtransform[boneweights->bone[1]]; + vec4_t *boneMat2 = (vec4_t *)g_studio.worldtransform[boneweights->bone[2]]; + flWeight0 = boneweights->weight[0] / 255.0f; + flWeight1 = boneweights->weight[1] / 255.0f; + flWeight2 = boneweights->weight[2] / 255.0f; + flTotal = flWeight0 + flWeight1 + flWeight2; + + if( flTotal < 1.0f ) flWeight0 += 1.0f - flTotal; // compensate rounding error + + result[0][0] = boneMat0[0][0] * flWeight0 + boneMat1[0][0] * flWeight1 + boneMat2[0][0] * flWeight2; + result[0][1] = boneMat0[0][1] * flWeight0 + boneMat1[0][1] * flWeight1 + boneMat2[0][1] * flWeight2; + result[0][2] = boneMat0[0][2] * flWeight0 + boneMat1[0][2] * flWeight1 + boneMat2[0][2] * flWeight2; + result[0][3] = boneMat0[0][3] * flWeight0 + boneMat1[0][3] * flWeight1 + boneMat2[0][3] * flWeight2; + result[1][0] = boneMat0[1][0] * flWeight0 + boneMat1[1][0] * flWeight1 + boneMat2[1][0] * flWeight2; + result[1][1] = boneMat0[1][1] * flWeight0 + boneMat1[1][1] * flWeight1 + boneMat2[1][1] * flWeight2; + result[1][2] = boneMat0[1][2] * flWeight0 + boneMat1[1][2] * flWeight1 + boneMat2[1][2] * flWeight2; + result[1][3] = boneMat0[1][3] * flWeight0 + boneMat1[1][3] * flWeight1 + boneMat2[1][3] * flWeight2; + result[2][0] = boneMat0[2][0] * flWeight0 + boneMat1[2][0] * flWeight1 + boneMat2[2][0] * flWeight2; + result[2][1] = boneMat0[2][1] * flWeight0 + boneMat1[2][1] * flWeight1 + boneMat2[2][1] * flWeight2; + result[2][2] = boneMat0[2][2] * flWeight0 + boneMat1[2][2] * flWeight1 + boneMat2[2][2] * flWeight2; + result[2][3] = boneMat0[2][3] * flWeight0 + boneMat1[2][3] * flWeight1 + boneMat2[2][3] * flWeight2; + } + else if( numbones == 2 ) + { + vec4_t *boneMat0 = (vec4_t *)g_studio.worldtransform[boneweights->bone[0]]; + vec4_t *boneMat1 = (vec4_t *)g_studio.worldtransform[boneweights->bone[1]]; + flWeight0 = boneweights->weight[0] / 255.0f; + flWeight1 = boneweights->weight[1] / 255.0f; + flTotal = flWeight0 + flWeight1; + + if( flTotal < 1.0f ) flWeight0 += 1.0f - flTotal; // compensate rounding error + + result[0][0] = boneMat0[0][0] * flWeight0 + boneMat1[0][0] * flWeight1; + result[0][1] = boneMat0[0][1] * flWeight0 + boneMat1[0][1] * flWeight1; + result[0][2] = boneMat0[0][2] * flWeight0 + boneMat1[0][2] * flWeight1; + result[0][3] = boneMat0[0][3] * flWeight0 + boneMat1[0][3] * flWeight1; + result[1][0] = boneMat0[1][0] * flWeight0 + boneMat1[1][0] * flWeight1; + result[1][1] = boneMat0[1][1] * flWeight0 + boneMat1[1][1] * flWeight1; + result[1][2] = boneMat0[1][2] * flWeight0 + boneMat1[1][2] * flWeight1; + result[1][3] = boneMat0[1][3] * flWeight0 + boneMat1[1][3] * flWeight1; + result[2][0] = boneMat0[2][0] * flWeight0 + boneMat1[2][0] * flWeight1; + result[2][1] = boneMat0[2][1] * flWeight0 + boneMat1[2][1] * flWeight1; + result[2][2] = boneMat0[2][2] * flWeight0 + boneMat1[2][2] * flWeight1; + result[2][3] = boneMat0[2][3] * flWeight0 + boneMat1[2][3] * flWeight1; + } + else + { + Matrix3x4_Copy( result, g_studio.worldtransform[boneweights->bone[0]] ); + } +} + +/* +=============== +pfnGetCurrentEntity + +=============== +*/ +static cl_entity_t *pfnGetCurrentEntity( void ) +{ + return RI.currententity; +} + +/* +=============== +pfnPlayerInfo + +=============== +*/ +player_info_t *pfnPlayerInfo( int index ) +{ + if( !RI.drawWorld ) + index = -1; + + return gEngfuncs.pfnPlayerInfo( index ); +} + +/* +=============== +pfnMod_ForName + +=============== +*/ +static model_t *pfnMod_ForName( const char *model, int crash ) +{ + return gEngfuncs.Mod_ForName( model, crash, false ); +} + +/* +=============== +pfnGetPlayerState + +=============== +*/ +entity_state_t *R_StudioGetPlayerState( int index ) +{ + if( !RI.drawWorld ) + return &RI.currententity->curstate; + + return gEngfuncs.pfnGetPlayerState( index ); +} + +/* +=============== +pfnGetViewEntity + +=============== +*/ +static cl_entity_t *pfnGetViewEntity( void ) +{ + return gEngfuncs.GetViewModel(); +} + +/* +=============== +pfnGetEngineTimes + +=============== +*/ +static void pfnGetEngineTimes( int *framecount, double *current, double *old ) +{ + if( framecount ) *framecount = tr.realframecount; + if( current ) *current = gpGlobals->time; + if( old ) *old = gpGlobals->oldtime; +} + +/* +=============== +pfnGetViewInfo + +=============== +*/ +static void pfnGetViewInfo( float *origin, float *upv, float *rightv, float *forwardv ) +{ + if( origin ) VectorCopy( RI.vieworg, origin ); + if( forwardv ) VectorCopy( RI.vforward, forwardv ); + if( rightv ) VectorCopy( RI.vright, rightv ); + if( upv ) VectorCopy( RI.vup, upv ); +} + +/* +=============== +R_GetChromeSprite + +=============== +*/ +static model_t *R_GetChromeSprite( void ) +{ + return gEngfuncs.GetDefaultSprite( REF_CHROME_SPRITE ); +} + +/* +=============== +pfnGetModelCounters + +=============== +*/ +static void pfnGetModelCounters( int **s, int **a ) +{ + *s = &g_studio.framecount; + *a = &r_stats.c_studio_models_drawn; +} + +/* +=============== +pfnGetAliasScale + +=============== +*/ +static void pfnGetAliasScale( float *x, float *y ) +{ + if( x ) *x = 1.0f; + if( y ) *y = 1.0f; +} + +/* +=============== +pfnStudioGetBoneTransform + +=============== +*/ +static float ****pfnStudioGetBoneTransform( void ) +{ + return (float ****)g_studio.bonestransform; +} + +/* +=============== +pfnStudioGetLightTransform + +=============== +*/ +static float ****pfnStudioGetLightTransform( void ) +{ + return (float ****)g_studio.lighttransform; +} + +/* +=============== +pfnStudioGetAliasTransform + +=============== +*/ +static float ***pfnStudioGetAliasTransform( void ) +{ + return NULL; +} + +/* +=============== +pfnStudioGetRotationMatrix + +=============== +*/ +static float ***pfnStudioGetRotationMatrix( void ) +{ + return (float ***)g_studio.rotationmatrix; +} + +/* +==================== +StudioPlayerBlend + +==================== +*/ +void R_StudioPlayerBlend( mstudioseqdesc_t *pseqdesc, int *pBlend, float *pPitch ) +{ + // calc up/down pointing + *pBlend = (*pPitch * 3.0f); + + if( *pBlend < pseqdesc->blendstart[0] ) + { + *pPitch -= pseqdesc->blendstart[0] / 3.0f; + *pBlend = 0; + } + else if( *pBlend > pseqdesc->blendend[0] ) + { + *pPitch -= pseqdesc->blendend[0] / 3.0f; + *pBlend = 255; + } + else + { + if( pseqdesc->blendend[0] - pseqdesc->blendstart[0] < 0.1f ) // catch qc error + *pBlend = 127; + else *pBlend = 255 * (*pBlend - pseqdesc->blendstart[0]) / (pseqdesc->blendend[0] - pseqdesc->blendstart[0]); + *pPitch = 0.0f; + } +} + +/* +==================== +R_StudioLerpMovement + +==================== +*/ +void R_StudioLerpMovement( cl_entity_t *e, double time, vec3_t origin, vec3_t angles ) +{ + float f = 1.0f; + + // don't do it if the goalstarttime hasn't updated in a while. + // NOTE: Because we need to interpolate multiplayer characters, the interpolation time limit + // was increased to 1.0 s., which is 2x the max lag we are accounting for. + if( g_studio.interpolate && ( time < e->curstate.animtime + 1.0f ) && ( e->curstate.animtime != e->latched.prevanimtime )) + f = ( time - e->curstate.animtime ) / ( e->curstate.animtime - e->latched.prevanimtime ); + + // Con_Printf( "%4.2f %.2f %.2f\n", f, e->curstate.animtime, g_studio.time ); + VectorLerp( e->latched.prevorigin, f, e->curstate.origin, origin ); + + if( !VectorCompareEpsilon( e->curstate.angles, e->latched.prevangles, ON_EPSILON )) + { + vec4_t q, q1, q2; + + AngleQuaternion( e->curstate.angles, q1, false ); + AngleQuaternion( e->latched.prevangles, q2, false ); + QuaternionSlerp( q2, q1, f, q ); + QuaternionAngle( q, angles ); + } + else VectorCopy( e->curstate.angles, angles ); +} + +/* +==================== +StudioSetUpTransform + +==================== +*/ +void R_StudioSetUpTransform( cl_entity_t *e ) +{ + vec3_t origin, angles; + + VectorCopy( e->origin, origin ); + VectorCopy( e->angles, angles ); + + // interpolate monsters position (moved into UpdateEntityFields by user request) + if( e->curstate.movetype == MOVETYPE_STEP && !FBitSet( ENGINE_GET_PARM( PARM_FEATURES ), ENGINE_COMPUTE_STUDIO_LERP )) + { + R_StudioLerpMovement( e, g_studio.time, origin, angles ); + } + + if( !FBitSet( ENGINE_GET_PARM( PARM_FEATURES ), ENGINE_COMPENSATE_QUAKE_BUG )) + angles[PITCH] = -angles[PITCH]; // stupid quake bug + + // don't rotate clients, only aim + if( e->player ) angles[PITCH] = 0.0f; + + Matrix3x4_CreateFromEntity( g_studio.rotationmatrix, angles, origin, 1.0f ); + + if( tr.fFlipViewModel ) + { + g_studio.rotationmatrix[0][1] = -g_studio.rotationmatrix[0][1]; + g_studio.rotationmatrix[1][1] = -g_studio.rotationmatrix[1][1]; + g_studio.rotationmatrix[2][1] = -g_studio.rotationmatrix[2][1]; + } +} + +/* +==================== +StudioEstimateFrame + +==================== +*/ +float R_StudioEstimateFrame( cl_entity_t *e, mstudioseqdesc_t *pseqdesc ) +{ + double dfdt, f; + + if( g_studio.interpolate ) + { + if( g_studio.time < e->curstate.animtime ) dfdt = 0.0; + else dfdt = (g_studio.time - e->curstate.animtime) * e->curstate.framerate * pseqdesc->fps; + } + else dfdt = 0; + + if( pseqdesc->numframes <= 1 ) f = 0.0; + else f = (e->curstate.frame * (pseqdesc->numframes - 1)) / 256.0; + + f += dfdt; + + if( pseqdesc->flags & STUDIO_LOOPING ) + { + if( pseqdesc->numframes > 1 ) + f -= (int)(f / (pseqdesc->numframes - 1)) * (pseqdesc->numframes - 1); + if( f < 0 ) f += (pseqdesc->numframes - 1); + } + else + { + if( f >= pseqdesc->numframes - 1.001 ) + f = pseqdesc->numframes - 1.001; + if( f < 0.0 ) f = 0.0; + } + return f; +} + +/* +==================== +StudioEstimateInterpolant + +==================== +*/ +float R_StudioEstimateInterpolant( cl_entity_t *e ) +{ + float dadt = 1.0f; + + if( g_studio.interpolate && ( e->curstate.animtime >= e->latched.prevanimtime + 0.01f )) + { + dadt = ( g_studio.time - e->curstate.animtime ) / 0.1f; + if( dadt > 2.0f ) dadt = 2.0f; + } + + return dadt; +} + +/* +==================== +CL_GetSequenceDuration + +==================== +*/ +float CL_GetSequenceDuration( cl_entity_t *ent, int sequence ) +{ + studiohdr_t *pstudiohdr; + mstudioseqdesc_t *pseqdesc; + + if( ent->model != NULL && ent->model->type == mod_studio ) + { + pstudiohdr = (studiohdr_t *)gEngfuncs.Mod_Extradata( mod_studio, ent->model ); + + if( pstudiohdr ) + { + sequence = bound( 0, sequence, pstudiohdr->numseq - 1 ); + pseqdesc = (mstudioseqdesc_t *)((byte *)pstudiohdr + pstudiohdr->seqindex) + sequence; + + if( pseqdesc->numframes > 1 && pseqdesc->fps > 0 ) + return (float)pseqdesc->numframes / (float)pseqdesc->fps; + } + } + + return 0.1f; +} + + +/* +==================== +StudioFxTransform + +==================== +*/ +void R_StudioFxTransform( cl_entity_t *ent, matrix3x4 transform ) +{ + switch( ent->curstate.renderfx ) + { + case kRenderFxDistort: + case kRenderFxHologram: + if( !gEngfuncs.COM_RandomLong( 0, 49 )) + { + int axis = gEngfuncs.COM_RandomLong( 0, 1 ); + + if( axis == 1 ) axis = 2; // choose between x & z + VectorScale( transform[axis], gEngfuncs.COM_RandomFloat( 1.0f, 1.484f ), transform[axis] ); + } + else if( !gEngfuncs.COM_RandomLong( 0, 49 )) + { + float offset; + int axis = gEngfuncs.COM_RandomLong( 0, 1 ); + + if( axis == 1 ) axis = 2; // choose between x & z + offset = gEngfuncs.COM_RandomFloat( -10.0f, 10.0f ); + transform[gEngfuncs.COM_RandomLong( 0, 2 )][3] += offset; + } + break; + case kRenderFxExplode: + { + float scale; + + scale = 1.0f + ( g_studio.time - ent->curstate.animtime ) * 10.0f; + if( scale > 2.0f ) scale = 2.0f; // don't blow up more than 200% + + transform[0][1] *= scale; + transform[1][1] *= scale; + transform[2][1] *= scale; + } + break; + } +} + +/* +==================== +StudioCalcBoneAdj + +==================== +*/ +void R_StudioCalcBoneAdj( float dadt, float *adj, const byte *pcontroller1, const byte *pcontroller2, byte mouthopen ) +{ + mstudiobonecontroller_t *pbonecontroller; + float value = 0.0f; + int i, j; + + pbonecontroller = (mstudiobonecontroller_t *)((byte *)m_pStudioHeader + m_pStudioHeader->bonecontrollerindex); + + for( j = 0; j < m_pStudioHeader->numbonecontrollers; j++ ) + { + i = pbonecontroller[j].index; + + if( i == STUDIO_MOUTH ) + { + // mouth hardcoded at controller 4 + value = (float)mouthopen / 64.0f; + value = bound( 0.0f, value, 1.0f ); + value = (1.0f - value) * pbonecontroller[j].start + value * pbonecontroller[j].end; + } + else if( i < 4 ) + { + // check for 360% wrapping + if( FBitSet( pbonecontroller[j].type, STUDIO_RLOOP )) + { + if( abs( pcontroller1[i] - pcontroller2[i] ) > 128 ) + { + int a = (pcontroller1[i] + 128) % 256; + int b = (pcontroller2[i] + 128) % 256; + value = (( a * dadt ) + ( b * ( 1.0f - dadt )) - 128) * (360.0f / 256.0f) + pbonecontroller[j].start; + } + else + { + value = ((pcontroller1[i] * dadt + (pcontroller2[i]) * (1.0f - dadt))) * (360.0f / 256.0f) + pbonecontroller[j].start; + } + } + else + { + value = (pcontroller1[i] * dadt + pcontroller2[i] * (1.0f - dadt)) / 255.0f; + value = bound( 0.0f, value, 1.0f ); + value = (1.0f - value) * pbonecontroller[j].start + value * pbonecontroller[j].end; + } + } + + switch( pbonecontroller[j].type & STUDIO_TYPES ) + { + case STUDIO_XR: + case STUDIO_YR: + case STUDIO_ZR: + adj[j] = DEG2RAD( value ); + break; + case STUDIO_X: + case STUDIO_Y: + case STUDIO_Z: + adj[j] = value; + break; + } + } +} + +/* +==================== +StudioCalcRotations + +==================== +*/ +void R_StudioCalcRotations( cl_entity_t *e, float pos[][3], vec4_t *q, mstudioseqdesc_t *pseqdesc, mstudioanim_t *panim, float f ) +{ + int i, frame; + float adj[MAXSTUDIOCONTROLLERS]; + float s, dadt; + mstudiobone_t *pbone; + + // bah, fix this bug with changing sequences too fast + if( f > pseqdesc->numframes - 1 ) + { + f = 0.0f; + } + else if( f < -0.01f ) + { + // BUG ( somewhere else ) but this code should validate this data. + // This could cause a crash if the frame # is negative, so we'll go ahead + // and clamp it here + f = -0.01f; + } + + frame = (int)f; + + dadt = R_StudioEstimateInterpolant( e ); + s = (f - frame); + + // add in programtic controllers + pbone = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); + + R_StudioCalcBoneAdj( dadt, adj, e->curstate.controller, e->latched.prevcontroller, e->mouth.mouthopen ); + + for( i = 0; i < m_pStudioHeader->numbones; i++, pbone++, panim++ ) + { + gEngfuncs.R_StudioCalcBoneQuaternion( frame, s, pbone, panim, adj, q[i] ); + gEngfuncs.R_StudioCalcBonePosition( frame, s, pbone, panim, adj, pos[i] ); + } + + if( pseqdesc->motiontype & STUDIO_X ) pos[pseqdesc->motionbone][0] = 0.0f; + if( pseqdesc->motiontype & STUDIO_Y ) pos[pseqdesc->motionbone][1] = 0.0f; + if( pseqdesc->motiontype & STUDIO_Z ) pos[pseqdesc->motionbone][2] = 0.0f; +} + +/* +==================== +StudioMergeBones + +==================== +*/ +void R_StudioMergeBones( cl_entity_t *e, model_t *m_pSubModel ) +{ + int i, j; + mstudiobone_t *pbones; + mstudioseqdesc_t *pseqdesc; + mstudioanim_t *panim; + matrix3x4 bonematrix; + static vec4_t q[MAXSTUDIOBONES]; + static float pos[MAXSTUDIOBONES][3]; + double f; + + if( e->curstate.sequence >= m_pStudioHeader->numseq ) + e->curstate.sequence = 0; + + pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + e->curstate.sequence; + + f = R_StudioEstimateFrame( e, pseqdesc ); + + panim = gEngfuncs.R_StudioGetAnim( m_pStudioHeader, m_pSubModel, pseqdesc ); + R_StudioCalcRotations( e, pos, q, pseqdesc, panim, f ); + pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); + + for( i = 0; i < m_pStudioHeader->numbones; i++ ) + { + for( j = 0; j < g_studio.cached_numbones; j++ ) + { + if( !Q_stricmp( pbones[i].name, g_studio.cached_bonenames[j] )) + { + Matrix3x4_Copy( g_studio.bonestransform[i], g_studio.cached_bonestransform[j] ); + Matrix3x4_Copy( g_studio.lighttransform[i], g_studio.cached_lighttransform[j] ); + break; + } + } + + if( j >= g_studio.cached_numbones ) + { + Matrix3x4_FromOriginQuat( bonematrix, q[i], pos[i] ); + if( pbones[i].parent == -1 ) + { + Matrix3x4_ConcatTransforms( g_studio.bonestransform[i], g_studio.rotationmatrix, bonematrix ); + Matrix3x4_Copy( g_studio.lighttransform[i], g_studio.bonestransform[i] ); + + // apply client-side effects to the transformation matrix + R_StudioFxTransform( e, g_studio.bonestransform[i] ); + } + else + { + Matrix3x4_ConcatTransforms( g_studio.bonestransform[i], g_studio.bonestransform[pbones[i].parent], bonematrix ); + Matrix3x4_ConcatTransforms( g_studio.lighttransform[i], g_studio.lighttransform[pbones[i].parent], bonematrix ); + } + } + } +} + +/* +==================== +StudioSetupBones + +==================== +*/ +void R_StudioSetupBones( cl_entity_t *e ) +{ + double f; + mstudiobone_t *pbones; + mstudioseqdesc_t *pseqdesc; + mstudioanim_t *panim; + matrix3x4 bonematrix; + static vec3_t pos[MAXSTUDIOBONES]; + static vec4_t q[MAXSTUDIOBONES]; + static vec3_t pos2[MAXSTUDIOBONES]; + static vec4_t q2[MAXSTUDIOBONES]; + static vec3_t pos3[MAXSTUDIOBONES]; + static vec4_t q3[MAXSTUDIOBONES]; + static vec3_t pos4[MAXSTUDIOBONES]; + static vec4_t q4[MAXSTUDIOBONES]; + int i; + + if( e->curstate.sequence >= m_pStudioHeader->numseq ) + e->curstate.sequence = 0; + + pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + e->curstate.sequence; + + f = R_StudioEstimateFrame( e, pseqdesc ); + + panim = gEngfuncs.R_StudioGetAnim( m_pStudioHeader, RI.currentmodel, pseqdesc ); + R_StudioCalcRotations( e, pos, q, pseqdesc, panim, f ); + + if( pseqdesc->numblends > 1 ) + { + float s; + float dadt; + + panim += m_pStudioHeader->numbones; + R_StudioCalcRotations( e, pos2, q2, pseqdesc, panim, f ); + + dadt = R_StudioEstimateInterpolant( e ); + s = (e->curstate.blending[0] * dadt + e->latched.prevblending[0] * (1.0f - dadt)) / 255.0f; + + gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q, pos, q2, pos2, s ); + + if( pseqdesc->numblends == 4 ) + { + panim += m_pStudioHeader->numbones; + R_StudioCalcRotations( e, pos3, q3, pseqdesc, panim, f ); + + panim += m_pStudioHeader->numbones; + R_StudioCalcRotations( e, pos4, q4, pseqdesc, panim, f ); + + s = (e->curstate.blending[0] * dadt + e->latched.prevblending[0] * (1.0f - dadt)) / 255.0f; + gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q3, pos3, q4, pos4, s ); + + s = (e->curstate.blending[1] * dadt + e->latched.prevblending[1] * (1.0f - dadt)) / 255.0f; + gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q, pos, q3, pos3, s ); + } + } + + if( g_studio.interpolate && e->latched.sequencetime && ( e->latched.sequencetime + 0.2f > g_studio.time ) && ( e->latched.prevsequence < m_pStudioHeader->numseq )) + { + // blend from last sequence + static vec3_t pos1b[MAXSTUDIOBONES]; + static vec4_t q1b[MAXSTUDIOBONES]; + float s; + + pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + e->latched.prevsequence; + panim = gEngfuncs.R_StudioGetAnim( m_pStudioHeader, RI.currentmodel, pseqdesc ); + + // clip prevframe + R_StudioCalcRotations( e, pos1b, q1b, pseqdesc, panim, e->latched.prevframe ); + + if( pseqdesc->numblends > 1 ) + { + panim += m_pStudioHeader->numbones; + R_StudioCalcRotations( e, pos2, q2, pseqdesc, panim, e->latched.prevframe ); + + s = (e->latched.prevseqblending[0]) / 255.0f; + gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q1b, pos1b, q2, pos2, s ); + + if( pseqdesc->numblends == 4 ) + { + panim += m_pStudioHeader->numbones; + R_StudioCalcRotations( e, pos3, q3, pseqdesc, panim, e->latched.prevframe ); + + panim += m_pStudioHeader->numbones; + R_StudioCalcRotations( e, pos4, q4, pseqdesc, panim, e->latched.prevframe ); + + s = (e->latched.prevseqblending[0]) / 255.0f; + gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q3, pos3, q4, pos4, s ); + + s = (e->latched.prevseqblending[1]) / 255.0f; + gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q1b, pos1b, q3, pos3, s ); + } + } + + s = 1.0f - ( g_studio.time - e->latched.sequencetime ) / 0.2f; + gEngfuncs.R_StudioSlerpBones( m_pStudioHeader->numbones, q, pos, q1b, pos1b, s ); + } + else + { + // store prevframe otherwise + e->latched.prevframe = f; + } + + pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); + + // calc gait animation + if( m_pPlayerInfo && m_pPlayerInfo->gaitsequence != 0 ) + { + qboolean copy_bones = true; + + if( m_pPlayerInfo->gaitsequence >= m_pStudioHeader->numseq ) + m_pPlayerInfo->gaitsequence = 0; + + pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pPlayerInfo->gaitsequence; + + panim = gEngfuncs.R_StudioGetAnim( m_pStudioHeader, RI.currentmodel, pseqdesc ); + R_StudioCalcRotations( e, pos2, q2, pseqdesc, panim, m_pPlayerInfo->gaitframe ); + + for( i = 0; i < m_pStudioHeader->numbones; i++ ) + { + if( !Q_strcmp( pbones[i].name, "Bip01 Spine" )) + copy_bones = false; + else if( !Q_strcmp( pbones[pbones[i].parent].name, "Bip01 Pelvis" )) + copy_bones = true; + + if( !copy_bones ) continue; + + VectorCopy( pos2[i], pos[i] ); + Vector4Copy( q2[i], q[i] ); + } + } + + for( i = 0; i < m_pStudioHeader->numbones; i++ ) + { + Matrix3x4_FromOriginQuat( bonematrix, q[i], pos[i] ); + + if( pbones[i].parent == -1 ) + { + Matrix3x4_ConcatTransforms( g_studio.bonestransform[i], g_studio.rotationmatrix, bonematrix ); + Matrix3x4_Copy( g_studio.lighttransform[i], g_studio.bonestransform[i] ); + + // apply client-side effects to the transformation matrix + R_StudioFxTransform( e, g_studio.bonestransform[i] ); + } + else + { + Matrix3x4_ConcatTransforms( g_studio.bonestransform[i], g_studio.bonestransform[pbones[i].parent], bonematrix ); + Matrix3x4_ConcatTransforms( g_studio.lighttransform[i], g_studio.lighttransform[pbones[i].parent], bonematrix ); + } + } +} + +/* +==================== +StudioSaveBones + +==================== +*/ +static void R_StudioSaveBones( void ) +{ + mstudiobone_t *pbones; + int i; + + pbones = (mstudiobone_t *)((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); + g_studio.cached_numbones = m_pStudioHeader->numbones; + + for( i = 0; i < m_pStudioHeader->numbones; i++ ) + { + Matrix3x4_Copy( g_studio.cached_bonestransform[i], g_studio.bonestransform[i] ); + Matrix3x4_Copy( g_studio.cached_lighttransform[i], g_studio.lighttransform[i] ); + Q_strncpy( g_studio.cached_bonenames[i], pbones[i].name, 32 ); + } +} + +/* +==================== +StudioBuildNormalTable + +NOTE: m_pSubModel must be set +==================== +*/ +void R_StudioBuildNormalTable( void ) +{ + cl_entity_t *e = RI.currententity; + mstudiomesh_t *pmesh; + int i, j; + + Assert( m_pSubModel != NULL ); + + // reset chrome cache + for( i = 0; i < m_pStudioHeader->numbones; i++ ) + g_studio.chromeage[i] = 0; + + for( i = 0; i < m_pSubModel->numverts; i++ ) + g_studio.normaltable[i] = -1; + + for( j = 0; j < m_pSubModel->nummesh; j++ ) + { + short *ptricmds; + + pmesh = (mstudiomesh_t *)((byte *)m_pStudioHeader + m_pSubModel->meshindex) + j; + ptricmds = (short *)((byte *)m_pStudioHeader + pmesh->triindex); + + while( i = *( ptricmds++ )) + { + if( i < 0 ) i = -i; + + for( ; i > 0; i--, ptricmds += 4 ) + { + if( g_studio.normaltable[ptricmds[0]] < 0 ) + g_studio.normaltable[ptricmds[0]] = ptricmds[1]; + } + } + } + + g_studio.chrome_origin[0] = cos( r_glowshellfreq->value * g_studio.time ) * 4000.0f; + g_studio.chrome_origin[1] = sin( r_glowshellfreq->value * g_studio.time ) * 4000.0f; + g_studio.chrome_origin[2] = cos( r_glowshellfreq->value * g_studio.time * 0.33f ) * 4000.0f; + + if( e->curstate.rendercolor.r || e->curstate.rendercolor.g || e->curstate.rendercolor.b ) + TriColor4ub( e->curstate.rendercolor.r, e->curstate.rendercolor.g, e->curstate.rendercolor.b, 255 ); + else TriColor4ub( 255, 255, 255, 255 ); +} + +/* +==================== +StudioGenerateNormals + +NOTE: m_pSubModel must be set +g_studio.verts must be computed +==================== +*/ +void R_StudioGenerateNormals( void ) +{ + int v0, v1, v2; + vec3_t e0, e1, norm; + mstudiomesh_t *pmesh; + int i, j; + + Assert( m_pSubModel != NULL ); + + for( i = 0; i < m_pSubModel->numverts; i++ ) + VectorClear( g_studio.norms[i] ); + + for( j = 0; j < m_pSubModel->nummesh; j++ ) + { + short *ptricmds; + + pmesh = (mstudiomesh_t *)((byte *)m_pStudioHeader + m_pSubModel->meshindex) + j; + ptricmds = (short *)((byte *)m_pStudioHeader + pmesh->triindex); + + while( i = *( ptricmds++ )) + { + if( i < 0 ) + { + i = -i; + + if( i > 2 ) + { + v0 = ptricmds[0]; ptricmds += 4; + v1 = ptricmds[0]; ptricmds += 4; + + for( i -= 2; i > 0; i--, ptricmds += 4 ) + { + v2 = ptricmds[0]; + + VectorSubtract( g_studio.verts[v1], g_studio.verts[v0], e0 ); + VectorSubtract( g_studio.verts[v2], g_studio.verts[v0], e1 ); + CrossProduct( e1, e0, norm ); + + VectorAdd( g_studio.norms[v0], norm, g_studio.norms[v0] ); + VectorAdd( g_studio.norms[v1], norm, g_studio.norms[v1] ); + VectorAdd( g_studio.norms[v2], norm, g_studio.norms[v2] ); + + v1 = v2; + } + } + else + { + ptricmds += i; + } + } + else + { + if( i > 2 ) + { + qboolean odd = false; + + v0 = ptricmds[0]; ptricmds += 4; + v1 = ptricmds[0]; ptricmds += 4; + + for( i -= 2; i > 0; i--, ptricmds += 4 ) + { + v2 = ptricmds[0]; + + VectorSubtract( g_studio.verts[v1], g_studio.verts[v0], e0 ); + VectorSubtract( g_studio.verts[v2], g_studio.verts[v0], e1 ); + CrossProduct( e1, e0, norm ); + + VectorAdd( g_studio.norms[v0], norm, g_studio.norms[v0] ); + VectorAdd( g_studio.norms[v1], norm, g_studio.norms[v1] ); + VectorAdd( g_studio.norms[v2], norm, g_studio.norms[v2] ); + + if( odd ) v1 = v2; + else v0 = v2; + + odd = !odd; + } + } + else + { + ptricmds += i; + } + } + } + } + + for( i = 0; i < m_pSubModel->numverts; i++ ) + VectorNormalize( g_studio.norms[i] ); +} + +/* +==================== +StudioSetupChrome + +==================== +*/ +void R_StudioSetupChrome( float *pchrome, int bone, vec3_t normal ) +{ + float n; + + if( g_studio.chromeage[bone] != g_studio.framecount ) + { + // calculate vectors from the viewer to the bone. This roughly adjusts for position + vec3_t chromeupvec; // g_studio.chrome t vector in world reference frame + vec3_t chromerightvec; // g_studio.chrome s vector in world reference frame + vec3_t tmp; // vector pointing at bone in world reference frame + + VectorNegate( g_studio.chrome_origin, tmp ); + tmp[0] += g_studio.bonestransform[bone][0][3]; + tmp[1] += g_studio.bonestransform[bone][1][3]; + tmp[2] += g_studio.bonestransform[bone][2][3]; + + VectorNormalize( tmp ); + CrossProduct( tmp, RI.vright, chromeupvec ); + VectorNormalize( chromeupvec ); + CrossProduct( tmp, chromeupvec, chromerightvec ); + VectorNormalize( chromerightvec ); + + Matrix3x4_VectorIRotate( g_studio.bonestransform[bone], chromeupvec, g_studio.chromeup[bone] ); + Matrix3x4_VectorIRotate( g_studio.bonestransform[bone], chromerightvec, g_studio.chromeright[bone] ); + + g_studio.chromeage[bone] = g_studio.framecount; + } + + // calc s coord + n = DotProduct( normal, g_studio.chromeright[bone] ); + pchrome[0] = (n + 1.0f) * 32.0f; + + // calc t coord + n = DotProduct( normal, g_studio.chromeup[bone] ); + pchrome[1] = (n + 1.0f) * 32.0f; +} + +/* +==================== +StudioCalcAttachments + +==================== +*/ +static void R_StudioCalcAttachments( void ) +{ + mstudioattachment_t *pAtt; + vec3_t forward, bonepos; + vec3_t localOrg, localAng; + int i; + + // calculate attachment points + pAtt = (mstudioattachment_t *)((byte *)m_pStudioHeader + m_pStudioHeader->attachmentindex); + + for( i = 0; i < Q_min( MAXSTUDIOATTACHMENTS, m_pStudioHeader->numattachments ); i++ ) + { + Matrix3x4_VectorTransform( g_studio.lighttransform[pAtt[i].bone], pAtt[i].org, RI.currententity->attachment[i] ); + VectorSubtract( RI.currententity->attachment[i], RI.currententity->origin, localOrg ); + Matrix3x4_OriginFromMatrix( g_studio.lighttransform[pAtt[i].bone], bonepos ); + VectorSubtract( localOrg, bonepos, forward ); // make forward + VectorNormalizeFast( forward ); + VectorAngles( forward, localAng ); + } +} + +/* +=============== +pfnStudioSetupModel + +=============== +*/ +static void R_StudioSetupModel( int bodypart, void **ppbodypart, void **ppsubmodel ) +{ + int index; + + if( bodypart > m_pStudioHeader->numbodyparts ) + bodypart = 0; + + m_pBodyPart = (mstudiobodyparts_t *)((byte *)m_pStudioHeader + m_pStudioHeader->bodypartindex) + bodypart; + + index = RI.currententity->curstate.body / m_pBodyPart->base; + index = index % m_pBodyPart->nummodels; + + m_pSubModel = (mstudiomodel_t *)((byte *)m_pStudioHeader + m_pBodyPart->modelindex) + index; + + if( ppbodypart ) *ppbodypart = m_pBodyPart; + if( ppsubmodel ) *ppsubmodel = m_pSubModel; +} + +/* +=============== +R_StudioCheckBBox + +=============== +*/ +static int R_StudioCheckBBox( void ) +{ + if( !RI.currententity || !RI.currentmodel ) + return false; + + return R_StudioComputeBBox( NULL ); +} + +/* +=============== +R_StudioDynamicLight + +=============== +*/ +void R_StudioDynamicLight( cl_entity_t *ent, alight_t *plight ) +{ + movevars_t *mv = gEngfuncs.pfnGetMoveVars(); + vec3_t lightDir, vecSrc, vecEnd; + vec3_t origin, dist, finalLight; + float add, radius, total; + colorVec light; + uint lnum; + dlight_t *dl; + + if( !plight || !ent || !ent->model ) + return; + + if( !RI.drawWorld || r_fullbright->value || FBitSet( ent->curstate.effects, EF_FULLBRIGHT )) + { + plight->shadelight = 0; + plight->ambientlight = 192; + + VectorSet( plight->plightvec, 0.0f, 0.0f, -1.0f ); + VectorSet( plight->color, 1.0f, 1.0f, 1.0f ); + return; + } + + // determine plane to get lightvalues from: ceil or floor + if( FBitSet( ent->curstate.effects, EF_INVLIGHT )) + VectorSet( lightDir, 0.0f, 0.0f, 1.0f ); + else VectorSet( lightDir, 0.0f, 0.0f, -1.0f ); + + VectorCopy( ent->origin, origin ); + + VectorSet( vecSrc, origin[0], origin[1], origin[2] - lightDir[2] * 8.0f ); + light.r = light.g = light.b = light.a = 0; + + if(( mv->skycolor_r + mv->skycolor_g + mv->skycolor_b ) != 0 ) + { + msurface_t *psurf = NULL; + pmtrace_t trace; + + if( FBitSet( ENGINE_GET_PARM( PARM_FEATURES ), ENGINE_WRITE_LARGE_COORD )) + { + vecEnd[0] = origin[0] - mv->skyvec_x * 65536.0f; + vecEnd[1] = origin[1] - mv->skyvec_y * 65536.0f; + vecEnd[2] = origin[2] - mv->skyvec_z * 65536.0f; + } + else + { + vecEnd[0] = origin[0] - mv->skyvec_x * 8192.0f; + vecEnd[1] = origin[1] - mv->skyvec_y * 8192.0f; + vecEnd[2] = origin[2] - mv->skyvec_z * 8192.0f; + } + + trace = gEngfuncs.CL_TraceLine( vecSrc, vecEnd, PM_WORLD_ONLY ); + if( trace.ent > 0 ) psurf = gEngfuncs.EV_TraceSurface( trace.ent, vecSrc, vecEnd ); + else psurf = gEngfuncs.EV_TraceSurface( 0, vecSrc, vecEnd ); + + if( FBitSet( ent->model->flags, STUDIO_FORCE_SKYLIGHT ) || ( psurf && FBitSet( psurf->flags, SURF_DRAWSKY ))) + { + VectorSet( lightDir, mv->skyvec_x, mv->skyvec_y, mv->skyvec_z ); + + light.r = gEngfuncs.LightToTexGamma( bound( 0, mv->skycolor_r, 255 )); + light.g = gEngfuncs.LightToTexGamma( bound( 0, mv->skycolor_g, 255 )); + light.b = gEngfuncs.LightToTexGamma( bound( 0, mv->skycolor_b, 255 )); + } + } + + if(( light.r + light.g + light.b ) < 16 ) // TESTTEST + { + colorVec gcolor; + float grad[4]; + + VectorScale( lightDir, 2048.0f, vecEnd ); + VectorAdd( vecEnd, vecSrc, vecEnd ); + + light = R_LightVec( vecSrc, vecEnd, g_studio.lightspot, g_studio.lightvec ); + + if( VectorIsNull( g_studio.lightvec )) + { + vecSrc[0] -= 16.0f; + vecSrc[1] -= 16.0f; + vecEnd[0] -= 16.0f; + vecEnd[1] -= 16.0f; + + gcolor = R_LightVec( vecSrc, vecEnd, NULL, NULL ); + grad[0] = ( gcolor.r + gcolor.g + gcolor.b ) / 768.0f; + + vecSrc[0] += 32.0f; + vecEnd[0] += 32.0f; + + gcolor = R_LightVec( vecSrc, vecEnd, NULL, NULL ); + grad[1] = ( gcolor.r + gcolor.g + gcolor.b ) / 768.0f; + + vecSrc[1] += 32.0f; + vecEnd[1] += 32.0f; + + gcolor = R_LightVec( vecSrc, vecEnd, NULL, NULL ); + grad[2] = ( gcolor.r + gcolor.g + gcolor.b ) / 768.0f; + + vecSrc[0] -= 32.0f; + vecEnd[0] -= 32.0f; + + gcolor = R_LightVec( vecSrc, vecEnd, NULL, NULL ); + grad[3] = ( gcolor.r + gcolor.g + gcolor.b ) / 768.0f; + + lightDir[0] = grad[0] - grad[1] - grad[2] + grad[3]; + lightDir[1] = grad[1] + grad[0] - grad[2] - grad[3]; + VectorNormalize( lightDir ); + } + else + { + VectorCopy( g_studio.lightvec, lightDir ); + } + } + + VectorSet( finalLight, light.r, light.g, light.b ); + ent->cvFloorColor = light; + + total = Q_max( Q_max( light.r, light.g ), light.b ); + if( total == 0.0f ) total = 1.0f; + + // scale lightdir by light intentsity + VectorScale( lightDir, total, lightDir ); + + for( lnum = 0; lnum < MAX_DLIGHTS; lnum++ ) + { + dl = gEngfuncs.GetDynamicLight( lnum ); + + if( dl->die < g_studio.time || !r_dynamic->value ) + continue; + + VectorSubtract( ent->origin, dl->origin, dist ); + + radius = VectorLength( dist ); + add = (dl->radius - radius); + + if( add > 0.0f ) + { + total += add; + + if( radius > 1.0f ) + VectorScale( dist, ( add / radius ), dist ); + else VectorScale( dist, add, dist ); + + VectorAdd( lightDir, dist, lightDir ); + + finalLight[0] += gEngfuncs.LightToTexGamma( dl->color.r ) * ( add / 256.0f ) * 2.0f; + finalLight[1] += gEngfuncs.LightToTexGamma( dl->color.g ) * ( add / 256.0f ) * 2.0f; + finalLight[2] += gEngfuncs.LightToTexGamma( dl->color.b ) * ( add / 256.0f ) * 2.0f; + } + } + + if( FBitSet( ent->model->flags, STUDIO_AMBIENT_LIGHT )) + add = 0.6f; + else add = 0.9f; + + VectorScale( lightDir, add, lightDir ); + + plight->shadelight = VectorLength( lightDir ); + plight->ambientlight = total - plight->shadelight; + + total = Q_max( Q_max( finalLight[0], finalLight[1] ), finalLight[2] ); + + if( total > 0.0f ) + { + plight->color[0] = finalLight[0] * ( 1.0f / total ); + plight->color[1] = finalLight[1] * ( 1.0f / total ); + plight->color[2] = finalLight[2] * ( 1.0f / total ); + } + else VectorSet( plight->color, 1.0f, 1.0f, 1.0f ); + + if( plight->ambientlight > 128 ) + plight->ambientlight = 128; + + if( plight->ambientlight + plight->shadelight > 255 ) + plight->shadelight = 255 - plight->ambientlight; + + VectorNormalize2( lightDir, plight->plightvec ); +} + +/* +=============== +pfnStudioEntityLight + +=============== +*/ +void R_StudioEntityLight( alight_t *lightinfo ) +{ + int lnum, i, j, k; + float minstrength, dist2, f, r2; + float lstrength[MAX_LOCALLIGHTS]; + cl_entity_t *ent = RI.currententity; + vec3_t mid, origin, pos; + dlight_t *el; + + g_studio.numlocallights = 0; + + if( !ent || !r_dynamic->value ) + return; + + for( i = 0; i < MAX_LOCALLIGHTS; i++ ) + lstrength[i] = 0; + + Matrix3x4_OriginFromMatrix( g_studio.rotationmatrix, origin ); + dist2 = 1000000.0f; + k = 0; + + for( lnum = 0; lnum < MAX_ELIGHTS; lnum++ ) + { + el = gEngfuncs.GetEntityLight( lnum ); + + if( el->die < g_studio.time || el->radius <= 0.0f ) + continue; + + if(( el->key & 0xFFF ) == ent->index ) + { + int att = (el->key >> 12) & 0xF; + + if( att ) VectorCopy( ent->attachment[att], el->origin ); + else VectorCopy( ent->origin, el->origin ); + } + + VectorCopy( el->origin, pos ); + VectorSubtract( origin, el->origin, mid ); + + f = DotProduct( mid, mid ); + r2 = el->radius * el->radius; + + if( f > r2 ) minstrength = r2 / f; + else minstrength = 1.0f; + + if( minstrength > 0.05f ) + { + if( g_studio.numlocallights >= MAX_LOCALLIGHTS ) + { + for( j = 0, k = -1; j < g_studio.numlocallights; j++ ) + { + if( lstrength[j] < dist2 && lstrength[j] < minstrength ) + { + dist2 = lstrength[j]; + k = j; + } + } + } + else k = g_studio.numlocallights; + + if( k != -1 ) + { + g_studio.locallightcolor[k].r = gEngfuncs.LightToTexGamma( el->color.r ); + g_studio.locallightcolor[k].g = gEngfuncs.LightToTexGamma( el->color.g ); + g_studio.locallightcolor[k].b = gEngfuncs.LightToTexGamma( el->color.b ); + g_studio.locallightR2[k] = r2; + g_studio.locallight[k] = el; + lstrength[k] = minstrength; + + if( k >= g_studio.numlocallights ) + g_studio.numlocallights = k + 1; + } + } + } +} + +/* +=============== +R_StudioSetupLighting + +=============== +*/ +void R_StudioSetupLighting( alight_t *plight ) +{ + float scale = 1.0f; + int i; + + if( !m_pStudioHeader || !plight ) + return; + + if( RI.currententity != NULL ) + scale = RI.currententity->curstate.scale; + + g_studio.ambientlight = plight->ambientlight; + g_studio.shadelight = plight->shadelight; + VectorCopy( plight->plightvec, g_studio.lightvec ); + + for( i = 0; i < m_pStudioHeader->numbones; i++ ) + { + Matrix3x4_VectorIRotate( g_studio.lighttransform[i], plight->plightvec, g_studio.blightvec[i] ); + if( scale > 1.0f ) VectorNormalize( g_studio.blightvec[i] ); // in case model may be scaled + } + + VectorCopy( plight->color, g_studio.lightcolor ); +} + +/* +=============== +R_StudioLighting + +=============== +*/ +void R_StudioLighting( float *lv, int bone, int flags, vec3_t normal ) +{ + float illum; + + if( FBitSet( flags, STUDIO_NF_FULLBRIGHT )) + { + *lv = 1.0f; + return; + } + + illum = g_studio.ambientlight; + + if( FBitSet( flags, STUDIO_NF_FLATSHADE )) + { + illum += g_studio.shadelight * 0.8f; + } + else + { + float r, lightcos; + + if( bone != -1 ) lightcos = DotProduct( normal, g_studio.blightvec[bone] ); + else lightcos = DotProduct( normal, g_studio.lightvec ); // -1 colinear, 1 opposite + if( lightcos > 1.0f ) lightcos = 1.0f; + + illum += g_studio.shadelight; + + r = SHADE_LAMBERT; + + // do modified hemispherical lighting + if( r <= 1.0f ) + { + r += 1.0f; + lightcos = (( r - 1.0f ) - lightcos) / r; + if( lightcos > 0.0f ) + illum += g_studio.shadelight * lightcos; + } + else + { + lightcos = (lightcos + ( r - 1.0f )) / r; + if( lightcos > 0.0f ) + illum -= g_studio.shadelight * lightcos; + } + + illum = Q_max( illum, 0.0f ); + } + + illum = Q_min( illum, 255.0f ); + *lv = illum * (1.0f / 255.0f); +} + +/* +==================== +R_LightLambert + +==================== +*/ +void R_LightLambert( vec4_t light[MAX_LOCALLIGHTS], vec3_t normal, vec3_t color, byte *out ) +{ + vec3_t finalLight; + vec3_t localLight; + int i; + + VectorCopy( color, finalLight ); + + for( i = 0; i < g_studio.numlocallights; i++ ) + { + float r, r2; + + if( tr.fFlipViewModel ) + r = DotProduct( normal, light[i] ); + else r = -DotProduct( normal, light[i] ); + + if( r > 0.0f ) + { + if( light[i][3] == 0.0f ) + { + r2 = DotProduct( light[i], light[i] ); + + if( r2 > 0.0f ) + light[i][3] = g_studio.locallightR2[i] / ( r2 * sqrt( r2 )); + else light[i][3] = 0.0001f; + } + + localLight[0] = Q_min( g_studio.locallightcolor[i].r * r * light[i][3], 255.0f ); + localLight[1] = Q_min( g_studio.locallightcolor[i].g * r * light[i][3], 255.0f ); + localLight[2] = Q_min( g_studio.locallightcolor[i].b * r * light[i][3], 255.0f ); + VectorScale( localLight, ( 1.0f / 255.0f ), localLight ); + + finalLight[0] = Q_min( finalLight[0] + localLight[0], 1.0f ); + finalLight[1] = Q_min( finalLight[1] + localLight[1], 1.0f ); + finalLight[2] = Q_min( finalLight[2] + localLight[2], 1.0f ); + } + } + + out[0] = finalLight[0] * 255; + out[1] = finalLight[1] * 255; + out[2] = finalLight[2] * 255; +} + +static void R_StudioSetColorBegin(short *ptricmds, vec3_t *pstudionorms ) +{ + float *lv = (float *)g_studio.lightvalues[ptricmds[1]]; + rgba_t color; + + if( g_studio.numlocallights ) + { + color[3] = tr.blend * 255; + R_LightLambert( g_studio.lightpos[ptricmds[0]], pstudionorms[ptricmds[1]], lv, color ); + //pglColor4ubv( color ); + TriColor4ub(color[0], color[1], color[2], color[3]); + } + else + { + if( RI.currententity->curstate.rendermode == kRenderTransColor ) + { + color[3] = tr.blend * 255; + VectorCopy( (byte*)&RI.currententity->curstate.rendercolor, color ); + //pglColor4ubv( color ); + } + else _TriColor4f( lv[0], lv[1], lv[2], tr.blend ); + } +} + + +/* +==================== +R_LightStrength + +==================== +*/ +void R_LightStrength( int bone, vec3_t localpos, vec4_t light[MAX_LOCALLIGHTS] ) +{ + int i; + + if( g_studio.lightage[bone] != g_studio.framecount ) + { + for( i = 0; i < g_studio.numlocallights; i++ ) + { + dlight_t *el = g_studio.locallight[i]; + Matrix3x4_VectorITransform( g_studio.lighttransform[bone], el->origin, g_studio.lightbonepos[bone][i] ); + } + + g_studio.lightage[bone] = g_studio.framecount; + } + + for( i = 0; i < g_studio.numlocallights; i++ ) + { + VectorSubtract( localpos, g_studio.lightbonepos[bone][i], light[i] ); + light[i][3] = 0.0f; + } +} + +/* +=============== +R_StudioSetupSkin + +=============== +*/ +static void R_StudioSetupSkin( studiohdr_t *ptexturehdr, int index ) +{ + mstudiotexture_t *ptexture = NULL; + + if( FBitSet( g_nForceFaceFlags, STUDIO_NF_CHROME )) + return; + + if( ptexturehdr == NULL ) + return; + + // NOTE: user may ignore to call StudioRemapColors and remap_info will be unavailable + if( m_fDoRemap ) ptexture = gEngfuncs.CL_GetRemapInfoForEntity( RI.currententity )->ptexture; + if( !ptexture ) ptexture = (mstudiotexture_t *)((byte *)ptexturehdr + ptexturehdr->textureindex); // fallback + + if( r_lightmap->value && !r_fullbright->value ) + GL_Bind( XASH_TEXTURE0, tr.whiteTexture ); + else GL_Bind( XASH_TEXTURE0, ptexture[index].index ); +} + +/* +=============== +R_StudioGetTexture + +Doesn't changes studio global state at all +=============== +*/ +mstudiotexture_t *R_StudioGetTexture( cl_entity_t *e ) +{ + mstudiotexture_t *ptexture; + studiohdr_t *phdr, *thdr; + + if(( phdr = gEngfuncs.Mod_Extradata( mod_studio, e->model )) == NULL ) + return NULL; + + thdr = m_pStudioHeader; + if( !thdr ) return NULL; + + if( m_fDoRemap ) ptexture = gEngfuncs.CL_GetRemapInfoForEntity( e )->ptexture; + else ptexture = (mstudiotexture_t *)((byte *)thdr + thdr->textureindex); + + return ptexture; +} + +void R_StudioSetRenderamt( int iRenderamt ) +{ + if( !RI.currententity ) return; + + RI.currententity->curstate.renderamt = iRenderamt; + tr.blend = gEngfuncs.CL_FxBlend( RI.currententity ) / 255.0f; +} + +/* +=============== +R_StudioSetCullState + +sets true for enable backculling (for left-hand viewmodel) +=============== +*/ +void R_StudioSetCullState( int iCull ) +{ + g_iBackFaceCull = iCull; +} + +/* +=============== +R_StudioRenderShadow + +just a prefab for render shadow +=============== +*/ +void R_StudioRenderShadow( int iSprite, float *p1, float *p2, float *p3, float *p4 ) +{ + if( !p1 || !p2 || !p3 || !p4 ) + return; + + if( TriSpriteTexture( gEngfuncs.pfnGetModelByIndex( iSprite ), 0 )) + { + TriRenderMode( kRenderTransAlpha ); + _TriColor4f( 0.0f, 0.0f, 0.0f, 1.0f ); + + TriBegin( TRI_QUADS ); + TriTexCoord2f( 0.0f, 0.0f ); + TriVertex3fv( p1 ); + TriTexCoord2f( 0.0f, 1.0f ); + TriVertex3fv( p2 ); + TriTexCoord2f( 1.0f, 1.0f ); + TriVertex3fv( p3 ); + TriTexCoord2f( 1.0f, 0.0f ); + TriVertex3fv( p4 ); + TriEnd(); + + TriRenderMode( kRenderNormal ); + } +} + +/* +=============== +R_StudioMeshCompare + +Sorting opaque entities by model type +=============== +*/ +static int R_StudioMeshCompare( const sortedmesh_t *a, const sortedmesh_t *b ) +{ + if( FBitSet( a->flags, STUDIO_NF_ADDITIVE )) + return 1; + + if( FBitSet( a->flags, STUDIO_NF_MASKED )) + return -1; + + return 0; +} + +/* +=============== +R_StudioDrawNormalMesh + +generic path +=============== +*/ +_inline void R_StudioDrawNormalMesh( short *ptricmds, vec3_t *pstudionorms, float s, float t ) +{ + float *lv; + int i; + + while( i = *( ptricmds++ )) + { + if( i < 0 ) + { + TriBegin( TRI_TRIANGLE_FAN ); + i = -i; + } + else TriBegin( TRI_TRIANGLE_STRIP ); + + for( ; i > 0; i--, ptricmds += 4 ) + { + R_StudioSetColorBegin( ptricmds, pstudionorms ); + + TriTexCoord2f( ptricmds[2] * s, ptricmds[3] * t ); + TriVertex3fv( g_studio.verts[ptricmds[0]] ); + } + + TriEnd(); + } +} + +/* +=============== +R_StudioDrawNormalMesh + +generic path +=============== +*/ +_inline void R_StudioDrawFloatMesh( short *ptricmds, vec3_t *pstudionorms ) +{ + float *lv; + int i; + + while( i = *( ptricmds++ )) + { + if( i < 0 ) + { + TriBegin( TRI_TRIANGLE_FAN ); + i = -i; + } + else TriBegin( TRI_TRIANGLE_STRIP ); + + for( ; i > 0; i--, ptricmds += 4 ) + { + R_StudioSetColorBegin( ptricmds, pstudionorms ); + TriTexCoord2f( HalfToFloat( ptricmds[2] ), HalfToFloat( ptricmds[3] )); + TriVertex3fv( g_studio.verts[ptricmds[0]] ); + } + + TriEnd(); + } +} + +/* +=============== +R_StudioDrawNormalMesh + +generic path +=============== +*/ +_inline void R_StudioDrawChromeMesh( short *ptricmds, vec3_t *pstudionorms, float s, float t, float scale ) +{ + float *lv, *av; + int i, idx; + qboolean glowShell = (scale > 0.0f) ? true : false; + vec3_t vert; + + while( i = *( ptricmds++ )) + { + if( i < 0 ) + { + TriBegin( TRI_TRIANGLE_FAN ); + i = -i; + } + else TriBegin( TRI_TRIANGLE_STRIP ); + + for( ; i > 0; i--, ptricmds += 4 ) + { + if( glowShell ) + { + color24 *clr = &RI.currententity->curstate.rendercolor; + + idx = g_studio.normaltable[ptricmds[0]]; + av = g_studio.verts[ptricmds[0]]; + lv = g_studio.norms[ptricmds[0]]; + VectorMA( av, scale, lv, vert ); + TriColor4ub( clr->r, clr->g, clr->b, 255 ); + TriTexCoord2f( g_studio.chrome[idx][0] * s, g_studio.chrome[idx][1] * t ); + TriVertex3fv( vert ); + } + else + { + idx = ptricmds[1]; + lv = (float *)g_studio.lightvalues[ptricmds[1]]; + R_StudioSetColorBegin( ptricmds, pstudionorms ); + TriTexCoord2f( g_studio.chrome[idx][0] * s, g_studio.chrome[idx][1] * t ); + TriVertex3fv( g_studio.verts[ptricmds[0]] ); + } + } + + TriEnd(); + } +} + + +/* +=============== +R_StudioDrawPoints + +=============== +*/ +static void R_StudioDrawPoints( void ) +{ + int i, j, k, m_skinnum; + float shellscale = 0.0f; + qboolean need_sort = false; + byte *pvertbone; + byte *pnormbone; + vec3_t *pstudioverts; + vec3_t *pstudionorms; + mstudiotexture_t *ptexture; + mstudiomesh_t *pmesh; + short *pskinref; + float lv_tmp; + + if( !m_pStudioHeader ) return; + + // safety bounding the skinnum + m_skinnum = bound( 0, RI.currententity->curstate.skin, ( m_pStudioHeader->numskinfamilies - 1 )); + ptexture = (mstudiotexture_t *)((byte *)m_pStudioHeader + m_pStudioHeader->textureindex); + pvertbone = ((byte *)m_pStudioHeader + m_pSubModel->vertinfoindex); + pnormbone = ((byte *)m_pStudioHeader + m_pSubModel->norminfoindex); + + pmesh = (mstudiomesh_t *)((byte *)m_pStudioHeader + m_pSubModel->meshindex); + pstudioverts = (vec3_t *)((byte *)m_pStudioHeader + m_pSubModel->vertindex); + pstudionorms = (vec3_t *)((byte *)m_pStudioHeader + m_pSubModel->normindex); + + pskinref = (short *)((byte *)m_pStudioHeader + m_pStudioHeader->skinindex); + if( m_skinnum != 0 ) pskinref += (m_skinnum * m_pStudioHeader->numskinref); + + if( FBitSet( m_pStudioHeader->flags, STUDIO_HAS_BONEWEIGHTS ) && m_pSubModel->blendvertinfoindex != 0 && m_pSubModel->blendnorminfoindex != 0 ) + { + mstudioboneweight_t *pvertweight = (mstudioboneweight_t *)((byte *)m_pStudioHeader + m_pSubModel->blendvertinfoindex); + mstudioboneweight_t *pnormweight = (mstudioboneweight_t *)((byte *)m_pStudioHeader + m_pSubModel->blendnorminfoindex); + matrix3x4 skinMat; + + for( i = 0; i < m_pSubModel->numverts; i++ ) + { + R_StudioComputeSkinMatrix( &pvertweight[i], skinMat ); + Matrix3x4_VectorTransform( skinMat, pstudioverts[i], g_studio.verts[i] ); + R_LightStrength( pvertbone[i], pstudioverts[i], g_studio.lightpos[i] ); + } + + for( i = 0; i < m_pSubModel->numnorms; i++ ) + { + R_StudioComputeSkinMatrix( &pnormweight[i], skinMat ); + Matrix3x4_VectorRotate( skinMat, pstudionorms[i], g_studio.norms[i] ); + } + } + else + { + for( i = 0; i < m_pSubModel->numverts; i++ ) + { + Matrix3x4_VectorTransform( g_studio.bonestransform[pvertbone[i]], pstudioverts[i], g_studio.verts[i] ); + R_LightStrength( pvertbone[i], pstudioverts[i], g_studio.lightpos[i] ); + } + } + + // generate shared normals for properly scaling glowing shell + if( RI.currententity->curstate.renderfx == kRenderFxGlowShell ) + { + float factor = (1.0f / 128.0f); + shellscale = Q_max( factor, RI.currententity->curstate.renderamt * factor ); + R_StudioBuildNormalTable(); + R_StudioGenerateNormals(); + } + + for( j = k = 0; j < m_pSubModel->nummesh; j++ ) + { + g_nFaceFlags = ptexture[pskinref[pmesh[j].skinref]].flags | g_nForceFaceFlags; + + // fill in sortedmesh info + g_studio.meshes[j].flags = g_nFaceFlags; + g_studio.meshes[j].mesh = &pmesh[j]; + + if( FBitSet( g_nFaceFlags, STUDIO_NF_MASKED|STUDIO_NF_ADDITIVE )) + need_sort = true; + + if( RI.currententity->curstate.rendermode == kRenderTransAdd ) + { + for( i = 0; i < pmesh[j].numnorms; i++, k++, pstudionorms++, pnormbone++ ) + { + if( FBitSet( g_nFaceFlags, STUDIO_NF_CHROME )) + R_StudioSetupChrome( g_studio.chrome[k], *pnormbone, (float *)pstudionorms ); + VectorSet( g_studio.lightvalues[k], tr.blend, tr.blend, tr.blend ); + } + } + else + { + for( i = 0; i < pmesh[j].numnorms; i++, k++, pstudionorms++, pnormbone++ ) + { + if( FBitSet( m_pStudioHeader->flags, STUDIO_HAS_BONEWEIGHTS )) + R_StudioLighting( &lv_tmp, -1, g_nFaceFlags, g_studio.norms[k] ); + else R_StudioLighting( &lv_tmp, *pnormbone, g_nFaceFlags, (float *)pstudionorms ); + + if( FBitSet( g_nFaceFlags, STUDIO_NF_CHROME )) + R_StudioSetupChrome( g_studio.chrome[k], *pnormbone, (float *)pstudionorms ); + VectorScale( g_studio.lightcolor, lv_tmp, g_studio.lightvalues[k] ); + } + } + } + + if( r_studio_sort_textures->value && need_sort ) + { + // resort opaque and translucent meshes draw order + qsort( g_studio.meshes, m_pSubModel->nummesh, sizeof( sortedmesh_t ), R_StudioMeshCompare ); + } + + // NOTE: rewind normals at start + pstudionorms = (vec3_t *)((byte *)m_pStudioHeader + m_pSubModel->normindex); + + for( j = 0; j < m_pSubModel->nummesh; j++ ) + { + float oldblend = tr.blend; + short *ptricmds; + float s, t; + + pmesh = g_studio.meshes[j].mesh; + ptricmds = (short *)((byte *)m_pStudioHeader + pmesh->triindex); + + g_nFaceFlags = ptexture[pskinref[pmesh->skinref]].flags | g_nForceFaceFlags; + + s = 1.0f / (float)ptexture[pskinref[pmesh->skinref]].width; + t = 1.0f / (float)ptexture[pskinref[pmesh->skinref]].height; + + if( FBitSet( g_nFaceFlags, STUDIO_NF_MASKED )) + { + //pglEnable( GL_ALPHA_TEST ); + //pglAlphaFunc( GL_GREATER, 0.5f ); + //pglDepthMask( GL_TRUE ); + if( R_ModelOpaque( RI.currententity->curstate.rendermode )) + tr.blend = 1.0f; + } + else if( FBitSet( g_nFaceFlags, STUDIO_NF_ADDITIVE )) + { + if( R_ModelOpaque( RI.currententity->curstate.rendermode )) + { + //pglBlendFunc( GL_ONE, GL_ONE ); + //pglDepthMask( GL_FALSE ); + //pglEnable( GL_BLEND ); + R_AllowFog( false ); + } + //else pglBlendFunc( GL_SRC_ALPHA, GL_ONE ); + } + + R_StudioSetupSkin( m_pStudioHeader, pskinref[pmesh->skinref] ); + + { + if( FBitSet( g_nFaceFlags, STUDIO_NF_CHROME )) + R_StudioDrawChromeMesh( ptricmds, pstudionorms, s, t, shellscale ); + else if( FBitSet( g_nFaceFlags, STUDIO_NF_UV_COORDS )) + R_StudioDrawFloatMesh( ptricmds, pstudionorms ); + else R_StudioDrawNormalMesh( ptricmds, pstudionorms, s, t ); + } + + if( FBitSet( g_nFaceFlags, STUDIO_NF_MASKED )) + { + //pglAlphaFunc( GL_GREATER, DEFAULT_ALPHATEST ); + //pglDisable( GL_ALPHA_TEST ); + } + else if( FBitSet( g_nFaceFlags, STUDIO_NF_ADDITIVE ) && R_ModelOpaque( RI.currententity->curstate.rendermode )) + { + //pglDepthMask( GL_TRUE ); + //pglDisable( GL_BLEND ); + R_AllowFog( true ); + } + + r_stats.c_studio_polys += pmesh->numtris; + tr.blend = oldblend; + } +} + +/* +=============== +R_StudioDrawHulls + +=============== +*/ +static void R_StudioDrawHulls( void ) +{ +#if 0 + float alpha, lv; + int i, j; + + if( r_drawentities->value == 4 ) + alpha = 0.5f; + else alpha = 1.0f; + + GL_Bind( XASH_TEXTURE0, tr.whiteTexture ); + //pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + + for( i = 0; i < m_pStudioHeader->numhitboxes; i++ ) + { + mstudiobbox_t *pbbox = (mstudiobbox_t *)((byte *)m_pStudioHeader + m_pStudioHeader->hitboxindex); + vec3_t tmp, p[8]; + + for( j = 0; j < 8; j++ ) + { + tmp[0] = (j & 1) ? pbbox[i].bbmin[0] : pbbox[i].bbmax[0]; + tmp[1] = (j & 2) ? pbbox[i].bbmin[1] : pbbox[i].bbmax[1]; + tmp[2] = (j & 4) ? pbbox[i].bbmin[2] : pbbox[i].bbmax[2]; + + Matrix3x4_VectorTransform( g_studio.bonestransform[pbbox[i].bone], tmp, p[j] ); + } + + j = (pbbox[i].group % 8); + + TriBegin( TRI_QUADS ); + _TriColor4f( hullcolor[j][0], hullcolor[j][1], hullcolor[j][2], alpha ); + + for( j = 0; j < 6; j++ ) + { + VectorClear( tmp ); + tmp[j % 3] = (j < 3) ? 1.0f : -1.0f; + R_StudioLighting( &lv, pbbox[i].bone, 0, tmp ); + + TriBrightness( lv ); + TriVertex3fv( p[boxpnt[j][0]] ); + TriVertex3fv( p[boxpnt[j][1]] ); + TriVertex3fv( p[boxpnt[j][2]] ); + TriVertex3fv( p[boxpnt[j][3]] ); + } + TriEnd(); + } +#endif +} + +/* +=============== +R_StudioDrawAbsBBox + +=============== +*/ +static void R_StudioDrawAbsBBox( void ) +{ + vec3_t p[8], tmp; + float lv; + int i; + + // looks ugly, skip + if( RI.currententity == gEngfuncs.GetViewModel() ) + return; + + if( !R_StudioComputeBBox( p )) + return; + + GL_Bind( XASH_TEXTURE0, tr.whiteTexture ); + _TriColor4f( 0.5f, 0.5f, 1.0f, 0.5f ); + TriRenderMode( kRenderTransAdd ); + + TriBegin( TRI_QUADS ); + for( i = 0; i < 6; i++ ) + { + VectorClear( tmp ); + tmp[i % 3] = (i < 3) ? 1.0f : -1.0f; + R_StudioLighting( &lv, -1, 0, tmp ); + + TriBrightness( lv ); + TriVertex3fv( p[boxpnt[i][0]] ); + TriVertex3fv( p[boxpnt[i][1]] ); + TriVertex3fv( p[boxpnt[i][2]] ); + TriVertex3fv( p[boxpnt[i][3]] ); + } + TriEnd(); + TriRenderMode( kRenderNormal ); +} + +/* +=============== +R_StudioDrawBones + +=============== +*/ +static void R_StudioDrawBones( void ) +{ + mstudiobone_t *pbones = (mstudiobone_t *) ((byte *)m_pStudioHeader + m_pStudioHeader->boneindex); + vec3_t point; + int i; +#if 0 + pglDisable( GL_TEXTURE_2D ); + + for( i = 0; i < m_pStudioHeader->numbones; i++ ) + { + if( pbones[i].parent >= 0 ) + { + pglPointSize( 3.0f ); + pglColor3f( 1, 0.7f, 0 ); + pglBegin( GL_LINES ); + + Matrix3x4_OriginFromMatrix( g_studio.bonestransform[pbones[i].parent], point ); + pglVertex3fv( point ); + Matrix3x4_OriginFromMatrix( g_studio.bonestransform[i], point ); + pglVertex3fv( point ); + + pglEnd(); + + pglColor3f( 0, 0, 0.8f ); + pglBegin( GL_POINTS ); + if( pbones[pbones[i].parent].parent != -1 ) + { + Matrix3x4_OriginFromMatrix( g_studio.bonestransform[pbones[i].parent], point ); + pglVertex3fv( point ); + } + Matrix3x4_OriginFromMatrix( g_studio.bonestransform[i], point ); + pglVertex3fv( point ); + pglEnd(); + } + else + { + // draw parent bone node + pglPointSize( 5.0f ); + pglColor3f( 0.8f, 0, 0 ); + pglBegin( GL_POINTS ); + Matrix3x4_OriginFromMatrix( g_studio.bonestransform[i], point ); + pglVertex3fv( point ); + pglEnd(); + } + } + + pglPointSize( 1.0f ); + pglEnable( GL_TEXTURE_2D ); +#endif +} + +static void R_StudioDrawAttachments( void ) +{ + int i; +#if 0 + pglDisable( GL_TEXTURE_2D ); + pglDisable( GL_DEPTH_TEST ); + + for( i = 0; i < m_pStudioHeader->numattachments; i++ ) + { + mstudioattachment_t *pattachments; + vec3_t v[4]; + + pattachments = (mstudioattachment_t *)((byte *)m_pStudioHeader + m_pStudioHeader->attachmentindex); + Matrix3x4_VectorTransform( g_studio.bonestransform[pattachments[i].bone], pattachments[i].org, v[0] ); + Matrix3x4_VectorTransform( g_studio.bonestransform[pattachments[i].bone], pattachments[i].vectors[0], v[1] ); + Matrix3x4_VectorTransform( g_studio.bonestransform[pattachments[i].bone], pattachments[i].vectors[1], v[2] ); + Matrix3x4_VectorTransform( g_studio.bonestransform[pattachments[i].bone], pattachments[i].vectors[2], v[3] ); + + pglBegin( GL_LINES ); + pglColor3f( 1, 0, 0 ); + pglVertex3fv( v[0] ); + pglColor3f( 1, 1, 1 ); + pglVertex3fv (v[1] ); + pglColor3f( 1, 0, 0 ); + pglVertex3fv (v[0] ); + pglColor3f( 1, 1, 1 ); + pglVertex3fv (v[2] ); + pglColor3f( 1, 0, 0 ); + pglVertex3fv (v[0] ); + pglColor3f( 1, 1, 1 ); + pglVertex3fv( v[3] ); + pglEnd(); + + pglPointSize( 5.0f ); + pglColor3f( 0, 1, 0 ); + pglBegin( GL_POINTS ); + pglVertex3fv( v[0] ); + pglEnd(); + pglPointSize( 1.0f ); + } + + pglEnable( GL_TEXTURE_2D ); + pglEnable( GL_DEPTH_TEST ); +#endif +} + +/* +=============== +R_StudioSetRemapColors + +=============== +*/ +static void R_StudioSetRemapColors( int newTop, int newBottom ) +{ + gEngfuncs.CL_AllocRemapInfo( newTop, newBottom ); + + if( gEngfuncs.CL_GetRemapInfoForEntity( RI.currententity )) + { + gEngfuncs.CL_UpdateRemapInfo( newTop, newBottom ); + m_fDoRemap = true; + } +} + +void R_StudioResetPlayerModels( void ) +{ + memset( g_studio.player_models, 0, sizeof( g_studio.player_models )); +} + +/* +=============== +R_StudioSetupPlayerModel + +=============== +*/ +static model_t *R_StudioSetupPlayerModel( int index ) +{ + player_info_t *info = gEngfuncs.pfnPlayerInfo( index ); + player_model_t *state; + + state = &g_studio.player_models[index]; + + // g-cont: force for "dev-mode", non-local games and menu preview + if(( gpGlobals->developer || !ENGINE_GET_PARM( PARM_LOCAL_GAME ) || !RI.drawWorld ) && info->model[0] ) + { + if( Q_strcmp( state->name, info->model )) + { + Q_strncpy( state->name, info->model, sizeof( state->name )); + state->name[sizeof( state->name ) - 1] = 0; + + Q_snprintf( state->modelname, sizeof( state->modelname ), "models/player/%s/%s.mdl", info->model, info->model ); + + if( gEngfuncs.FS_FileExists( state->modelname, false )) + state->model = gEngfuncs.Mod_ForName( state->modelname, false, true ); + else state->model = NULL; + + if( !state->model ) + state->model = RI.currententity->model; + } + } + else + { + if( state->model != RI.currententity->model ) + state->model = RI.currententity->model; + state->name[0] = 0; + } + + return state->model; +} + +/* +================ +R_GetEntityRenderMode + +check for texture flags +================ +*/ +int R_GetEntityRenderMode( cl_entity_t *ent ) +{ + int i, opaque, trans; + mstudiotexture_t *ptexture; + cl_entity_t *oldent; + model_t *model; + studiohdr_t *phdr; + + oldent = RI.currententity; + RI.currententity = ent; + + if( ent->player ) // check it for real playermodel + model = R_StudioSetupPlayerModel( ent->curstate.number - 1 ); + else model = ent->model; + + RI.currententity = oldent; + + if(( phdr = gEngfuncs.Mod_Extradata( mod_studio, model )) == NULL ) + { + if( R_ModelOpaque( ent->curstate.rendermode )) + { + // forcing to choose right sorting type + if(( model && model->type == mod_brush ) && FBitSet( model->flags, MODEL_TRANSPARENT )) + return kRenderTransAlpha; + } + return ent->curstate.rendermode; + } + ptexture = (mstudiotexture_t *)((byte *)phdr + phdr->textureindex); + + for( opaque = trans = i = 0; i < phdr->numtextures; i++, ptexture++ ) + { + // ignore chrome & additive it's just a specular-like effect + if( FBitSet( ptexture->flags, STUDIO_NF_ADDITIVE ) && !FBitSet( ptexture->flags, STUDIO_NF_CHROME )) + trans++; + else opaque++; + } + + // if model is more additive than opaque + if( trans > opaque ) + return kRenderTransAdd; + return ent->curstate.rendermode; +} + +/* +=============== +R_StudioClientEvents + +=============== +*/ +static void R_StudioClientEvents( void ) +{ + mstudioseqdesc_t *pseqdesc; + mstudioevent_t *pevent; + cl_entity_t *e = RI.currententity; + int i, sequence; + float end, start; + + if( g_studio.frametime == 0.0 ) + return; // gamepaused + + // fill attachments with interpolated origin + if( m_pStudioHeader->numattachments <= 0 ) + { + Matrix3x4_OriginFromMatrix( g_studio.rotationmatrix, e->attachment[0] ); + Matrix3x4_OriginFromMatrix( g_studio.rotationmatrix, e->attachment[1] ); + Matrix3x4_OriginFromMatrix( g_studio.rotationmatrix, e->attachment[2] ); + Matrix3x4_OriginFromMatrix( g_studio.rotationmatrix, e->attachment[3] ); + } + + if( FBitSet( e->curstate.effects, EF_MUZZLEFLASH )) + { + dlight_t *el = gEngfuncs.CL_AllocElight( 0 ); + + ClearBits( e->curstate.effects, EF_MUZZLEFLASH ); + VectorCopy( e->attachment[0], el->origin ); + el->die = gpGlobals->time + 0.05f; + el->color.r = 255; + el->color.g = 192; + el->color.b = 64; + el->decay = 320; + el->radius = 24; + } + + sequence = bound( 0, e->curstate.sequence, m_pStudioHeader->numseq - 1 ); + pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + sequence; + + // no events for this animation + if( pseqdesc->numevents == 0 ) + return; + + end = R_StudioEstimateFrame( e, pseqdesc ); + start = end - e->curstate.framerate * gpGlobals->frametime * pseqdesc->fps; + pevent = (mstudioevent_t *)((byte *)m_pStudioHeader + pseqdesc->eventindex); + + if( e->latched.sequencetime == e->curstate.animtime ) + { + if( !FBitSet( pseqdesc->flags, STUDIO_LOOPING )) + start = -0.01f; + } + + for( i = 0; i < pseqdesc->numevents; i++ ) + { + // ignore all non-client-side events + if( pevent[i].event < EVENT_CLIENT ) + continue; + + if( (float)pevent[i].frame > start && pevent[i].frame <= end ) + gEngfuncs.pfnStudioEvent( &pevent[i], e ); + } +} + +/* +=============== +R_StudioGetForceFaceFlags + +=============== +*/ +int R_StudioGetForceFaceFlags( void ) +{ + return g_nForceFaceFlags; +} + +/* +=============== +R_StudioSetForceFaceFlags + +=============== +*/ +void R_StudioSetForceFaceFlags( int flags ) +{ + g_nForceFaceFlags = flags; +} + +/* +=============== +pfnStudioSetHeader + +=============== +*/ +void R_StudioSetHeader( studiohdr_t *pheader ) +{ + m_pStudioHeader = pheader; + m_fDoRemap = false; +} + +/* +=============== +R_StudioSetRenderModel + +=============== +*/ +void R_StudioSetRenderModel( model_t *model ) +{ + RI.currentmodel = model; +} + +/* +=============== +R_StudioSetupRenderer + +=============== +*/ +static void R_StudioSetupRenderer( int rendermode ) +{ + studiohdr_t *phdr = m_pStudioHeader; + int i; + + if( rendermode > kRenderTransAdd ) rendermode = 0; + g_studio.rendermode = bound( 0, rendermode, kRenderTransAdd ); + + //pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + //pglDisable( GL_ALPHA_TEST ); + //pglShadeModel( GL_SMOOTH ); + + // a point to setup local to world transform for boneweighted models + if( phdr && FBitSet( phdr->flags, STUDIO_HAS_BONEINFO )) + { + // NOTE: extended boneinfo goes immediately after bones + mstudioboneinfo_t *boneinfo = (mstudioboneinfo_t *)((byte *)phdr + phdr->boneindex + phdr->numbones * sizeof( mstudiobone_t )); + + for( i = 0; i < phdr->numbones; i++ ) + Matrix3x4_ConcatTransforms( g_studio.worldtransform[i], g_studio.bonestransform[i], boneinfo[i].poseToBone ); + } +} + +/* +=============== +R_StudioRestoreRenderer + +=============== +*/ +static void R_StudioRestoreRenderer( void ) +{ + //if( g_studio.rendermode != kRenderNormal ) + //pglDisable( GL_BLEND ); + + //pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); + //pglShadeModel( GL_FLAT ); + m_fDoRemap = false; +} + +/* +=============== +R_StudioSetChromeOrigin + +=============== +*/ +void R_StudioSetChromeOrigin( void ) +{ + VectorCopy( RI.vieworg, g_studio.chrome_origin ); +} + +/* +=============== +pfnIsHardware + +Xash3D is always works in hardware mode +=============== +*/ +static int pfnIsHardware( void ) +{ + return 1; // 0 is Software, 1 is OpenGL, 2 is Direct3D +} + +/* +=============== +R_StudioDrawPointsShadow + +=============== +*/ +static void R_StudioDrawPointsShadow( void ) +{ + float *av, height; + float vec_x, vec_y; + mstudiomesh_t *pmesh; + vec3_t point; + int i, k; + + if( FBitSet( RI.currententity->curstate.effects, EF_NOSHADOW )) + return; + + //if( glState.stencilEnabled ) + //pglEnable( GL_STENCIL_TEST ); + + height = g_studio.lightspot[2] + 1.0f; + vec_x = -g_studio.lightvec[0] * 8.0f; + vec_y = -g_studio.lightvec[1] * 8.0f; + + for( k = 0; k < m_pSubModel->nummesh; k++ ) + { + short *ptricmds; + + pmesh = (mstudiomesh_t *)((byte *)m_pStudioHeader + m_pSubModel->meshindex) + k; + ptricmds = (short *)((byte *)m_pStudioHeader + pmesh->triindex); + + r_stats.c_studio_polys += pmesh->numtris; + + while( i = *( ptricmds++ )) + { + if( i < 0 ) + { + TriBegin( TRI_TRIANGLE_FAN ); + i = -i; + } + else + { + TriBegin( TRI_TRIANGLE_STRIP ); + } + + + for( ; i > 0; i--, ptricmds += 4 ) + { + av = g_studio.verts[ptricmds[0]]; + point[0] = av[0] - (vec_x * ( av[2] - g_studio.lightspot[2] )); + point[1] = av[1] - (vec_y * ( av[2] - g_studio.lightspot[2] )); + point[2] = g_studio.lightspot[2] + 1.0f; + + TriVertex3fv( point ); + } + + TriEnd(); + } + } + + //if( glState.stencilEnabled ) + //pglDisable( GL_STENCIL_TEST ); +} + +/* +=============== +GL_StudioSetRenderMode + +set rendermode for studiomodel +=============== +*/ +void GL_StudioSetRenderMode( int rendermode ) +{ +#if 0 + switch( rendermode ) + { + case kRenderNormal: + break; + case kRenderTransColor: + pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + pglEnable( GL_BLEND ); + break; + case kRenderTransAdd: + pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + pglColor4f( tr.blend, tr.blend, tr.blend, 1.0f ); + pglBlendFunc( GL_ONE, GL_ONE ); + pglDepthMask( GL_FALSE ); + pglEnable( GL_BLEND ); + break; + default: + pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + pglColor4f( 1.0f, 1.0f, 1.0f, tr.blend ); + pglDepthMask( GL_TRUE ); + pglEnable( GL_BLEND ); + break; + } +#endif +} + +/* +=============== +GL_StudioDrawShadow + +g-cont: don't modify this code it's 100% matched with +original GoldSrc code and used in some mods to enable +studio shadows with some asm tricks +=============== +*/ +static void GL_StudioDrawShadow( void ) +{ +#if 0 + pglDepthMask( GL_TRUE ); + + if( r_shadows.value && g_studio.rendermode != kRenderTransAdd && !FBitSet( RI.currentmodel->flags, STUDIO_AMBIENT_LIGHT )) + { + float color = 1.0 - (tr.blend * 0.5); + + pglDisable( GL_TEXTURE_2D ); + pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + pglEnable( GL_BLEND ); + pglColor4f( 0.0f, 0.0f, 0.0f, 1.0f - color ); + + pglDepthFunc( GL_LESS ); + R_StudioDrawPointsShadow(); + pglDepthFunc( GL_LEQUAL ); + + pglEnable( GL_TEXTURE_2D ); + pglDisable( GL_BLEND ); + pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); + pglShadeModel( GL_SMOOTH ); + } +#endif +} + +/* +==================== +StudioRenderFinal + +==================== +*/ +void R_StudioRenderFinal( void ) +{ + int i, rendermode; + + rendermode = R_StudioGetForceFaceFlags() ? kRenderTransAdd : RI.currententity->curstate.rendermode; + R_StudioSetupRenderer( rendermode ); + + if( r_drawentities->value == 2 ) + { + R_StudioDrawBones(); + } + else if( r_drawentities->value == 3 ) + { + R_StudioDrawHulls(); + } + else + { + for( i = 0; i < m_pStudioHeader->numbodyparts; i++ ) + { + R_StudioSetupModel( i, &m_pBodyPart, &m_pSubModel ); + + GL_StudioSetRenderMode( rendermode ); + R_StudioDrawPoints(); + GL_StudioDrawShadow(); + } + } + + if( r_drawentities->value == 4 ) + { + TriRenderMode( kRenderTransAdd ); + R_StudioDrawHulls( ); + TriRenderMode( kRenderNormal ); + } + + if( r_drawentities->value == 5 ) + { + R_StudioDrawAbsBBox( ); + } + + if( r_drawentities->value == 6 ) + { + R_StudioDrawAttachments(); + } +#if 0 + if( r_drawentities->value == 7 ) + { + vec3_t origin; + + pglDisable( GL_TEXTURE_2D ); + pglDisable( GL_DEPTH_TEST ); + + Matrix3x4_OriginFromMatrix( g_studio.rotationmatrix, origin ); + + pglBegin( GL_LINES ); + pglColor3f( 1, 0.5, 0 ); + pglVertex3fv( origin ); + pglVertex3fv( g_studio.lightspot ); + pglEnd(); + + pglBegin( GL_LINES ); + pglColor3f( 0, 0.5, 1 ); + VectorMA( g_studio.lightspot, -64.0f, g_studio.lightvec, origin ); + pglVertex3fv( g_studio.lightspot ); + pglVertex3fv( origin ); + pglEnd(); + + pglPointSize( 5.0f ); + pglColor3f( 1, 0, 0 ); + pglBegin( GL_POINTS ); + pglVertex3fv( g_studio.lightspot ); + pglEnd(); + pglPointSize( 1.0f ); + + pglEnable( GL_DEPTH_TEST ); + pglEnable( GL_TEXTURE_2D ); + } + + R_StudioRestoreRenderer(); +#endif +} + +/* +==================== +StudioRenderModel + +==================== +*/ +void R_StudioRenderModel( void ) +{ + R_StudioSetChromeOrigin(); + R_StudioSetForceFaceFlags( 0 ); + + if( RI.currententity->curstate.renderfx == kRenderFxGlowShell ) + { + RI.currententity->curstate.renderfx = kRenderFxNone; + + R_StudioRenderFinal( ); + + R_StudioSetForceFaceFlags( STUDIO_NF_CHROME ); + TriSpriteTexture( R_GetChromeSprite(), 0 ); + RI.currententity->curstate.renderfx = kRenderFxGlowShell; + + R_StudioRenderFinal( ); + } + else + { + R_StudioRenderFinal( ); + } +} + +/* +==================== +StudioEstimateGait + +==================== +*/ +void R_StudioEstimateGait( entity_state_t *pplayer ) +{ + vec3_t est_velocity; + float dt; + + dt = bound( 0.0f, g_studio.frametime, 1.0f ); + + if( dt == 0.0f || m_pPlayerInfo->renderframe == tr.realframecount ) + { + m_flGaitMovement = 0; + return; + } + + VectorSubtract( RI.currententity->origin, m_pPlayerInfo->prevgaitorigin, est_velocity ); + VectorCopy( RI.currententity->origin, m_pPlayerInfo->prevgaitorigin ); + m_flGaitMovement = VectorLength( est_velocity ); + + if( dt <= 0.0f || m_flGaitMovement / dt < 5.0f ) + { + m_flGaitMovement = 0.0f; + est_velocity[0] = 0.0f; + est_velocity[1] = 0.0f; + } + + if( est_velocity[1] == 0.0f && est_velocity[0] == 0.0f ) + { + float flYawDiff = RI.currententity->angles[YAW] - m_pPlayerInfo->gaityaw; + + flYawDiff = flYawDiff - (int)(flYawDiff / 360) * 360; + if( flYawDiff > 180.0f ) flYawDiff -= 360.0f; + if( flYawDiff < -180.0f ) flYawDiff += 360.0f; + + if( dt < 0.25f ) + flYawDiff *= dt * 4.0f; + else flYawDiff *= dt; + + m_pPlayerInfo->gaityaw += flYawDiff; + m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - (int)(m_pPlayerInfo->gaityaw / 360) * 360; + + m_flGaitMovement = 0.0f; + } + else + { + m_pPlayerInfo->gaityaw = ( atan2( est_velocity[1], est_velocity[0] ) * 180 / M_PI ); + if( m_pPlayerInfo->gaityaw > 180.0f ) m_pPlayerInfo->gaityaw = 180.0f; + if( m_pPlayerInfo->gaityaw < -180.0f ) m_pPlayerInfo->gaityaw = -180.0f; + } + +} + +/* +==================== +StudioProcessGait + +==================== +*/ +void R_StudioProcessGait( entity_state_t *pplayer ) +{ + mstudioseqdesc_t *pseqdesc; + int iBlend; + float dt, flYaw; // view direction relative to movement + + if( RI.currententity->curstate.sequence >= m_pStudioHeader->numseq ) + RI.currententity->curstate.sequence = 0; + + dt = bound( 0.0f, g_studio.frametime, 1.0f ); + + pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + RI.currententity->curstate.sequence; + + R_StudioPlayerBlend( pseqdesc, &iBlend, &RI.currententity->angles[PITCH] ); + + RI.currententity->latched.prevangles[PITCH] = RI.currententity->angles[PITCH]; + RI.currententity->curstate.blending[0] = iBlend; + RI.currententity->latched.prevblending[0] = RI.currententity->curstate.blending[0]; + RI.currententity->latched.prevseqblending[0] = RI.currententity->curstate.blending[0]; + R_StudioEstimateGait( pplayer ); + + // calc side to side turning + flYaw = RI.currententity->angles[YAW] - m_pPlayerInfo->gaityaw; + flYaw = flYaw - (int)(flYaw / 360) * 360; + if( flYaw < -180.0f ) flYaw = flYaw + 360.0f; + if( flYaw > 180.0f ) flYaw = flYaw - 360.0f; + + if( flYaw > 120.0f ) + { + m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw - 180.0f; + m_flGaitMovement = -m_flGaitMovement; + flYaw = flYaw - 180.0f; + } + else if( flYaw < -120.0f ) + { + m_pPlayerInfo->gaityaw = m_pPlayerInfo->gaityaw + 180.0f; + m_flGaitMovement = -m_flGaitMovement; + flYaw = flYaw + 180.0f; + } + + // adjust torso + RI.currententity->curstate.controller[0] = ((flYaw / 4.0f) + 30.0f) / (60.0f / 255.0f); + RI.currententity->curstate.controller[1] = ((flYaw / 4.0f) + 30.0f) / (60.0f / 255.0f); + RI.currententity->curstate.controller[2] = ((flYaw / 4.0f) + 30.0f) / (60.0f / 255.0f); + RI.currententity->curstate.controller[3] = ((flYaw / 4.0f) + 30.0f) / (60.0f / 255.0f); + RI.currententity->latched.prevcontroller[0] = RI.currententity->curstate.controller[0]; + RI.currententity->latched.prevcontroller[1] = RI.currententity->curstate.controller[1]; + RI.currententity->latched.prevcontroller[2] = RI.currententity->curstate.controller[2]; + RI.currententity->latched.prevcontroller[3] = RI.currententity->curstate.controller[3]; + + RI.currententity->angles[YAW] = m_pPlayerInfo->gaityaw; + if( RI.currententity->angles[YAW] < -0 ) RI.currententity->angles[YAW] += 360.0f; + RI.currententity->latched.prevangles[YAW] = RI.currententity->angles[YAW]; + + if( pplayer->gaitsequence >= m_pStudioHeader->numseq ) + pplayer->gaitsequence = 0; + + pseqdesc = (mstudioseqdesc_t *)((byte *)m_pStudioHeader + m_pStudioHeader->seqindex) + pplayer->gaitsequence; + + // calc gait frame + if( pseqdesc->linearmovement[0] > 0 ) + m_pPlayerInfo->gaitframe += (m_flGaitMovement / pseqdesc->linearmovement[0]) * pseqdesc->numframes; + else m_pPlayerInfo->gaitframe += pseqdesc->fps * dt; + + // do modulo + m_pPlayerInfo->gaitframe = m_pPlayerInfo->gaitframe - (int)(m_pPlayerInfo->gaitframe / pseqdesc->numframes) * pseqdesc->numframes; + if( m_pPlayerInfo->gaitframe < 0 ) m_pPlayerInfo->gaitframe += pseqdesc->numframes; +} + +/* +=============== +R_StudioDrawPlayer + +=============== +*/ +static int R_StudioDrawPlayer( int flags, entity_state_t *pplayer ) +{ + int m_nPlayerIndex; + alight_t lighting; + vec3_t dir; + + m_nPlayerIndex = pplayer->number - 1; + + if( m_nPlayerIndex < 0 || m_nPlayerIndex >= ENGINE_GET_PARM( PARM_MAX_CLIENTS ) ) + return 0; + + RI.currentmodel = R_StudioSetupPlayerModel( m_nPlayerIndex ); + if( RI.currentmodel == NULL ) + return 0; + + R_StudioSetHeader((studiohdr_t *)gEngfuncs.Mod_Extradata( mod_studio, RI.currentmodel )); + + if( pplayer->gaitsequence ) + { + vec3_t orig_angles; + + m_pPlayerInfo = pfnPlayerInfo( m_nPlayerIndex ); + VectorCopy( RI.currententity->angles, orig_angles ); + + R_StudioProcessGait( pplayer ); + + m_pPlayerInfo->gaitsequence = pplayer->gaitsequence; + m_pPlayerInfo = NULL; + + R_StudioSetUpTransform( RI.currententity ); + VectorCopy( orig_angles, RI.currententity->angles ); + } + else + { + RI.currententity->curstate.controller[0] = 127; + RI.currententity->curstate.controller[1] = 127; + RI.currententity->curstate.controller[2] = 127; + RI.currententity->curstate.controller[3] = 127; + RI.currententity->latched.prevcontroller[0] = RI.currententity->curstate.controller[0]; + RI.currententity->latched.prevcontroller[1] = RI.currententity->curstate.controller[1]; + RI.currententity->latched.prevcontroller[2] = RI.currententity->curstate.controller[2]; + RI.currententity->latched.prevcontroller[3] = RI.currententity->curstate.controller[3]; + + m_pPlayerInfo = pfnPlayerInfo( m_nPlayerIndex ); + m_pPlayerInfo->gaitsequence = 0; + + R_StudioSetUpTransform( RI.currententity ); + } + + if( flags & STUDIO_RENDER ) + { + // see if the bounding box lets us trivially reject, also sets + if( !R_StudioCheckBBox( )) + return 0; + + r_stats.c_studio_models_drawn++; + g_studio.framecount++; // render data cache cookie + + if( m_pStudioHeader->numbodyparts == 0 ) + return 1; + } + + m_pPlayerInfo = pfnPlayerInfo( m_nPlayerIndex ); + R_StudioSetupBones( RI.currententity ); + R_StudioSaveBones( ); + + m_pPlayerInfo->renderframe = tr.realframecount; + m_pPlayerInfo = NULL; + + if( flags & STUDIO_EVENTS ) + { + R_StudioCalcAttachments( ); + R_StudioClientEvents( ); + + // copy attachments into global entity array + if( RI.currententity->index > 0 ) + { + cl_entity_t *ent = gEngfuncs.GetEntityByIndex( RI.currententity->index ); + memcpy( ent->attachment, RI.currententity->attachment, sizeof( vec3_t ) * 4 ); + } + } + + if( flags & STUDIO_RENDER ) + { + if( cl_himodels->value && RI.currentmodel != RI.currententity->model ) + { + // show highest resolution multiplayer model + RI.currententity->curstate.body = 255; + } + + if( !( !gpGlobals->developer && ENGINE_GET_PARM( PARM_MAX_CLIENTS ) == 1 ) && ( RI.currentmodel == RI.currententity->model )) + RI.currententity->curstate.body = 1; // force helmet + + lighting.plightvec = dir; + R_StudioDynamicLight( RI.currententity, &lighting ); + + R_StudioEntityLight( &lighting ); + + // model and frame independant + R_StudioSetupLighting( &lighting ); + + m_pPlayerInfo = pfnPlayerInfo( m_nPlayerIndex ); + + // get remap colors + g_nTopColor = m_pPlayerInfo->topcolor; + g_nBottomColor = m_pPlayerInfo->bottomcolor; + + if( g_nTopColor < 0 ) g_nTopColor = 0; + if( g_nTopColor > 360 ) g_nTopColor = 360; + if( g_nBottomColor < 0 ) g_nBottomColor = 0; + if( g_nBottomColor > 360 ) g_nBottomColor = 360; + + R_StudioSetRemapColors( g_nTopColor, g_nBottomColor ); + + R_StudioRenderModel( ); + m_pPlayerInfo = NULL; + + if( pplayer->weaponmodel ) + { + cl_entity_t saveent = *RI.currententity; + model_t *pweaponmodel = gEngfuncs.pfnGetModelByIndex( pplayer->weaponmodel ); + + m_pStudioHeader = (studiohdr_t *)gEngfuncs.Mod_Extradata( mod_studio, pweaponmodel ); + + R_StudioMergeBones( RI.currententity, pweaponmodel ); + R_StudioSetupLighting( &lighting ); + R_StudioRenderModel( ); + R_StudioCalcAttachments( ); + + *RI.currententity = saveent; + } + } + + return 1; +} + +/* +=============== +R_StudioDrawModel + +=============== +*/ +static int R_StudioDrawModel( int flags ) +{ + alight_t lighting; + vec3_t dir; + + if( RI.currententity->curstate.renderfx == kRenderFxDeadPlayer ) + { + entity_state_t deadplayer; + int result; + + if( RI.currententity->curstate.renderamt <= 0 || + RI.currententity->curstate.renderamt > ENGINE_GET_PARM( PARM_MAX_CLIENTS ) ) + return 0; + + // get copy of player + deadplayer = *R_StudioGetPlayerState( RI.currententity->curstate.renderamt - 1 ); + + // clear weapon, movement state + deadplayer.number = RI.currententity->curstate.renderamt; + deadplayer.weaponmodel = 0; + deadplayer.gaitsequence = 0; + + deadplayer.movetype = MOVETYPE_NONE; + VectorCopy( RI.currententity->curstate.angles, deadplayer.angles ); + VectorCopy( RI.currententity->curstate.origin, deadplayer.origin ); + + g_studio.interpolate = false; + result = R_StudioDrawPlayer( flags, &deadplayer ); // draw as though it were a player + g_studio.interpolate = true; + + return result; + } + + R_StudioSetHeader((studiohdr_t *)gEngfuncs.Mod_Extradata( mod_studio, RI.currentmodel )); + + R_StudioSetUpTransform( RI.currententity ); + + if( flags & STUDIO_RENDER ) + { + // see if the bounding box lets us trivially reject, also sets + if( !R_StudioCheckBBox( )) + return 0; + + r_stats.c_studio_models_drawn++; + g_studio.framecount++; // render data cache cookie + + if( m_pStudioHeader->numbodyparts == 0 ) + return 1; + } + + if( RI.currententity->curstate.movetype == MOVETYPE_FOLLOW ) + R_StudioMergeBones( RI.currententity, RI.currentmodel ); + else R_StudioSetupBones( RI.currententity ); + + R_StudioSaveBones(); + + if( flags & STUDIO_EVENTS ) + { + R_StudioCalcAttachments( ); + R_StudioClientEvents( ); + + // copy attachments into global entity array + if( RI.currententity->index > 0 ) + { + cl_entity_t *ent = gEngfuncs.GetEntityByIndex( RI.currententity->index ); + memcpy( ent->attachment, RI.currententity->attachment, sizeof( vec3_t ) * 4 ); + } + } + + if( flags & STUDIO_RENDER ) + { + lighting.plightvec = dir; + R_StudioDynamicLight( RI.currententity, &lighting ); + + R_StudioEntityLight( &lighting ); + + // model and frame independant + R_StudioSetupLighting( &lighting ); + + // get remap colors + g_nTopColor = RI.currententity->curstate.colormap & 0xFF; + g_nBottomColor = (RI.currententity->curstate.colormap & 0xFF00) >> 8; + + R_StudioSetRemapColors( g_nTopColor, g_nBottomColor ); + + R_StudioRenderModel(); + } + + return 1; +} + +/* +================= +R_StudioDrawModelInternal +================= +*/ +void R_StudioDrawModelInternal( cl_entity_t *e, int flags ) +{ + if( !RI.drawWorld ) + { + if( e->player ) + R_StudioDrawPlayer( flags, &e->curstate ); + else R_StudioDrawModel( flags ); + } + else + { + // select the properly method + if( e->player ) + pStudioDraw->StudioDrawPlayer( flags, R_StudioGetPlayerState( e->index - 1 )); + else pStudioDraw->StudioDrawModel( flags ); + } +} + +/* +================= +R_DrawStudioModel +================= +*/ +void R_DrawStudioModel( cl_entity_t *e ) +{ + if( FBitSet( RI.params, RP_ENVVIEW )) + return; + + R_StudioSetupTimings(); + + if( e->player ) + { + R_StudioDrawModelInternal( e, STUDIO_RENDER|STUDIO_EVENTS ); + } + else + { + if( e->curstate.movetype == MOVETYPE_FOLLOW && e->curstate.aiment > 0 ) + { + cl_entity_t *parent = gEngfuncs.GetEntityByIndex( e->curstate.aiment ); + + if( parent && parent->model && parent->model->type == mod_studio ) + { + RI.currententity = parent; + R_StudioDrawModelInternal( RI.currententity, 0 ); + VectorCopy( parent->curstate.origin, e->curstate.origin ); + VectorCopy( parent->origin, e->origin ); + RI.currententity = e; + } + } + + R_StudioDrawModelInternal( e, STUDIO_RENDER|STUDIO_EVENTS ); + } +} + +/* +================= +R_RunViewmodelEvents +================= +*/ +void R_RunViewmodelEvents( void ) +{ + int i; + vec3_t simorg; + + if( r_drawviewmodel->value == 0 ) + return; + + if( ENGINE_GET_PARM( PARM_THIRDPERSON )) + return; + + // ignore in thirdperson, camera view or client is died + if( !RP_NORMALPASS() || ENGINE_GET_PARM( PARM_LOCAL_HEALTH ) <= 0 || !CL_IsViewEntityLocalPlayer()) + return; + + RI.currententity = gEngfuncs.GetViewModel(); + + if( !RI.currententity->model || RI.currententity->model->type != mod_studio ) + return; + + R_StudioSetupTimings(); + + gEngfuncs.GetPredictedOrigin( simorg ); + for( i = 0; i < 4; i++ ) + VectorCopy( simorg, RI.currententity->attachment[i] ); + RI.currentmodel = RI.currententity->model; + + R_StudioDrawModelInternal( RI.currententity, STUDIO_EVENTS ); +} + +/* +================= +R_GatherPlayerLight +================= +*/ +void R_GatherPlayerLight( void ) +{ + cl_entity_t *view = gEngfuncs.GetViewModel(); + colorVec c; + + tr.ignore_lightgamma = true; + c = R_LightPoint( view->origin ); + tr.ignore_lightgamma = false; + gEngfuncs.SetLocalLightLevel( ( c.r + c.g + c.b ) / 3 ); +} + +/* +================= +R_DrawViewModel +================= +*/ +void R_DrawViewModel( void ) +{ + cl_entity_t *view = gEngfuncs.GetViewModel(); + + R_GatherPlayerLight(); + + if( r_drawviewmodel->value == 0 ) + return; + + if( ENGINE_GET_PARM( PARM_THIRDPERSON )) + return; + + // ignore in thirdperson, camera view or client is died + if( !RP_NORMALPASS() || ENGINE_GET_PARM( PARM_LOCAL_HEALTH ) <= 0 || !CL_IsViewEntityLocalPlayer()) + return; + + tr.blend = gEngfuncs.CL_FxBlend( view ) / 255.0f; + if( !R_ModelOpaque( view->curstate.rendermode ) && tr.blend <= 0.0f ) + return; // invisible ? + + RI.currententity = view; + + if( !RI.currententity->model ) + return; + + // adjust the depth range to prevent view model from poking into walls + //pglDepthRange( gldepthmin, gldepthmin + 0.3f * ( gldepthmax - gldepthmin )); + /// TODO: ziscale + RI.currentmodel = RI.currententity->model; + + // backface culling for left-handed weapons + if( R_AllowFlipViewModel( RI.currententity ) || g_iBackFaceCull ) + { + tr.fFlipViewModel = true; + //pglFrontFace( GL_CW ); + } + + switch( RI.currententity->model->type ) + { + case mod_alias: + // R_DrawAliasModel( RI.currententity ); + break; + case mod_studio: + R_StudioSetupTimings(); + R_StudioDrawModelInternal( RI.currententity, STUDIO_RENDER ); + break; + } + + // restore depth range + //pglDepthRange( gldepthmin, gldepthmax ); + /// ziscale + + // backface culling for left-handed weapons + if( R_AllowFlipViewModel( RI.currententity ) || g_iBackFaceCull ) + { + tr.fFlipViewModel = false; + //pglFrontFace( GL_CCW ); + } +} + +/* +==================== +R_StudioLoadTexture + +load model texture with unique name +==================== +*/ +static void R_StudioLoadTexture( model_t *mod, studiohdr_t *phdr, mstudiotexture_t *ptexture ) +{ + size_t size; + int flags = 0; + char texname[128], name[128], mdlname[128]; + texture_t *tx = NULL; + + if( ptexture->flags & STUDIO_NF_NORMALMAP ) + flags |= (TF_NORMALMAP); + + // store some textures for remapping + if( !Q_strnicmp( ptexture->name, "DM_Base", 7 ) || !Q_strnicmp( ptexture->name, "remap", 5 )) + { + int i, size; + char val[6]; + byte *pixels; + + i = mod->numtextures; + mod->textures = (texture_t **)Mem_Realloc( mod->mempool, mod->textures, ( i + 1 ) * sizeof( texture_t* )); + size = ptexture->width * ptexture->height + 768; + tx = Mem_Calloc( mod->mempool, sizeof( *tx ) + size ); + mod->textures[i] = tx; + + // store ranges into anim_min, anim_max etc + if( !Q_strnicmp( ptexture->name, "DM_Base", 7 )) + { + Q_strncpy( tx->name, "DM_Base", sizeof( tx->name )); + tx->anim_min = PLATE_HUE_START; // topcolor start + tx->anim_max = PLATE_HUE_END; // topcolor end + // bottomcolor start always equal is (topcolor end + 1) + tx->anim_total = SUIT_HUE_END;// bottomcolor end + } + else + { + Q_strncpy( tx->name, "DM_User", sizeof( tx->name )); // custom remapped + Q_strncpy( val, ptexture->name + 7, 4 ); + tx->anim_min = bound( 0, Q_atoi( val ), 255 ); // topcolor start + Q_strncpy( val, ptexture->name + 11, 4 ); + tx->anim_max = bound( 0, Q_atoi( val ), 255 ); // topcolor end + // bottomcolor start always equal is (topcolor end + 1) + Q_strncpy( val, ptexture->name + 15, 4 ); + tx->anim_total = bound( 0, Q_atoi( val ), 255 ); // bottomcolor end + } + + tx->width = ptexture->width; + tx->height = ptexture->height; + + // the pixels immediately follow the structures + pixels = (byte *)phdr + ptexture->index; + memcpy( tx+1, pixels, size ); + + ptexture->flags |= STUDIO_NF_COLORMAP; // yes, this is colormap image + flags |= TF_FORCE_COLOR; + + mod->numtextures++; // done + } + + Q_strncpy( mdlname, mod->name, sizeof( mdlname )); + COM_FileBase( ptexture->name, name ); + COM_StripExtension( mdlname ); + + if( FBitSet( ptexture->flags, STUDIO_NF_NOMIPS )) + SetBits( flags, TF_NOMIPMAP ); + + // NOTE: replace index with pointer to start of imagebuffer, ImageLib expected it + //ptexture->index = (int)((byte *)phdr) + ptexture->index; + gEngfuncs.Image_SetMDLPointer((byte *)phdr + ptexture->index); + size = sizeof( mstudiotexture_t ) + ptexture->width * ptexture->height + 768; + + if( FBitSet( ENGINE_GET_PARM( PARM_FEATURES ), ENGINE_LOAD_DELUXEDATA ) && FBitSet( ptexture->flags, STUDIO_NF_MASKED )) + flags |= TF_KEEP_SOURCE; // Paranoia2 texture alpha-tracing + + // build the texname + Q_snprintf( texname, sizeof( texname ), "#%s/%s.mdl", mdlname, name ); + ptexture->index = GL_LoadTexture( texname, (byte *)ptexture, size, flags ); + + if( !ptexture->index ) + { + ptexture->index = tr.defaultTexture; + } + else if( tx ) + { + // duplicate texnum for easy acess + tx->gl_texturenum = ptexture->index; + } +} + +/* +================= +Mod_StudioLoadTextures +================= +*/ +void Mod_StudioLoadTextures( model_t *mod, void *data ) +{ + studiohdr_t *phdr = (studiohdr_t *)data; + mstudiotexture_t *ptexture; + int i; + + if( !phdr ) + return; + + ptexture = (mstudiotexture_t *)(((byte *)phdr) + phdr->textureindex); + if( phdr->textureindex > 0 && phdr->numtextures <= MAXSTUDIOSKINS ) + { + for( i = 0; i < phdr->numtextures; i++ ) + R_StudioLoadTexture( mod, phdr, &ptexture[i] ); + } +} + +/* +================= +Mod_StudioUnloadTextures +================= +*/ +void Mod_StudioUnloadTextures( void *data ) +{ + studiohdr_t *phdr = (studiohdr_t *)data; + mstudiotexture_t *ptexture; + int i; + + if( !phdr ) + return; + + ptexture = (mstudiotexture_t *)(((byte *)phdr) + phdr->textureindex); + + // release all textures + for( i = 0; i < phdr->numtextures; i++ ) + { + if( ptexture[i].index == tr.defaultTexture ) + continue; + GL_FreeTexture( ptexture[i].index ); + } +} + +static model_t *pfnModelHandle( int modelindex ) +{ + return gEngfuncs.pfnGetModelByIndex( modelindex ); +} + +static void *pfnMod_CacheCheck( struct cache_user_s *c ) +{ + return gEngfuncs.Mod_CacheCheck( c ); +} + +static void *pfnMod_StudioExtradata( model_t *mod ) +{ + return gEngfuncs.Mod_Extradata( mod_studio, mod ); +} + +static void pfnMod_LoadCacheFile( const char *path, struct cache_user_s *cu ) +{ + gEngfuncs.Mod_LoadCacheFile( path, cu ); +} + +static cvar_t *pfnGetCvarPointer( const char *name ) +{ + return (cvar_t*)gEngfuncs.pfnGetCvarPointer( name, 0 ); +} + +static void *pfnMod_Calloc( int number, size_t size ) +{ + return gEngfuncs.Mod_Calloc( number, size ); +} + +static engine_studio_api_t gStudioAPI = +{ + pfnMod_Calloc, + pfnMod_CacheCheck, + pfnMod_LoadCacheFile, + pfnMod_ForName, + pfnMod_StudioExtradata, + pfnModelHandle, + pfnGetCurrentEntity, + pfnPlayerInfo, + R_StudioGetPlayerState, + pfnGetViewEntity, + pfnGetEngineTimes, + pfnGetCvarPointer, + pfnGetViewInfo, + R_GetChromeSprite, + pfnGetModelCounters, + pfnGetAliasScale, + pfnStudioGetBoneTransform, + pfnStudioGetLightTransform, + pfnStudioGetAliasTransform, + pfnStudioGetRotationMatrix, + R_StudioSetupModel, + R_StudioCheckBBox, + R_StudioDynamicLight, + R_StudioEntityLight, + R_StudioSetupLighting, + R_StudioDrawPoints, + R_StudioDrawHulls, + R_StudioDrawAbsBBox, + R_StudioDrawBones, + (void*)R_StudioSetupSkin, + R_StudioSetRemapColors, + R_StudioSetupPlayerModel, + R_StudioClientEvents, + R_StudioGetForceFaceFlags, + R_StudioSetForceFaceFlags, + (void*)R_StudioSetHeader, + R_StudioSetRenderModel, + R_StudioSetupRenderer, + R_StudioRestoreRenderer, + R_StudioSetChromeOrigin, + pfnIsHardware, + GL_StudioDrawShadow, + GL_StudioSetRenderMode, + R_StudioSetRenderamt, + R_StudioSetCullState, + R_StudioRenderShadow, +}; + +static r_studio_interface_t gStudioDraw = +{ + STUDIO_INTERFACE_VERSION, + R_StudioDrawModel, + R_StudioDrawPlayer, +}; + +/* +=============== +CL_InitStudioAPI + +Initialize client studio +=============== +*/ +void CL_InitStudioAPI( void ) +{ + pStudioDraw = &gStudioDraw; + + // trying to grab them from client.dll + cl_righthand = gEngfuncs.pfnGetCvarPointer( "cl_righthand", 0 ); + + if( cl_righthand == NULL ) + cl_righthand = gEngfuncs.Cvar_Get( "cl_righthand", "0", FCVAR_ARCHIVE, "flip viewmodel (left to right)" ); + + // Xash will be used internal StudioModelRenderer + if( gEngfuncs.pfnGetStudioModelInterface( STUDIO_INTERFACE_VERSION, &pStudioDraw, &gStudioAPI )) + return; + + // NOTE: we always return true even if game interface was not correct + // because we need Draw our StudioModels + // just restore pointer to builtin function + pStudioDraw = &gStudioDraw; +} diff --git a/r_triapi.c b/r_triapi.c index 47b81e6c..27210b52 100644 --- a/r_triapi.c +++ b/r_triapi.c @@ -23,6 +23,10 @@ static struct vec4_t triRGBA; } ds; +finalvert_t triv[3]; +int vertcount; +int mode; + /* =============================================================== @@ -76,7 +80,7 @@ TriBegin begin triangle sequence ============= */ -void TriBegin( int mode ) +void TriBegin( int mode1 ) { #if 0 switch( mode ) @@ -110,6 +114,8 @@ void TriBegin( int mode ) pglBegin( mode ); #endif + mode = mode1; + vertcount = 0; } /* @@ -121,6 +127,8 @@ draw triangle sequence */ void TriEnd( void ) { + //if( vertcount == 3 ) + R_RenderTriangle( triv ); //pglEnd( ); } @@ -212,6 +220,7 @@ TriVertex3fv void TriVertex3fv( const float *v ) { //pglVertex3fv( v ); + TriVertex3f( v[0], v[1], v[2] ); } /* @@ -222,7 +231,37 @@ TriVertex3f */ void TriVertex3f( float x, float y, float z ) { - //pglVertex3f( x, y, z ); + if( mode == TRI_TRIANGLE_FAN ) + { + R_SetupFinalVert( &triv[vertcount], x, y, z, 0,0,0); + vertcount++; + if( vertcount >= 3 ) + { + R_RenderTriangle( triv ); + triv[1] = triv[2]; + vertcount = 2; + } + } + if( mode == TRI_TRIANGLE_STRIP ) + { + R_SetupFinalVert( &triv[vertcount], x, y, z, 0,0,0); + vertcount++; + if( vertcount == 3 ) + { + R_RenderTriangle( triv ); + finalvert_t fv = triv[0]; + + triv[0] = triv[2]; + triv[2] = fv; + R_RenderTriangle( triv ); + fv = triv[0]; + triv[0] = triv[2]; + triv[2] = fv; + triv[0] = triv[1]; + triv[1] = triv[2]; + vertcount = 2; + } + } } /* From 224bf07930e47f479a9bd125945dab085d10fe26 Mon Sep 17 00:00:00 2001 From: mittorn Date: Tue, 26 Mar 2019 06:01:20 +0700 Subject: [PATCH 026/115] ref_soft: Fix TRIANGLE_STRIP draw --- r_triapi.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/r_triapi.c b/r_triapi.c index 27210b52..15011d4b 100644 --- a/r_triapi.c +++ b/r_triapi.c @@ -244,23 +244,14 @@ void TriVertex3f( float x, float y, float z ) } if( mode == TRI_TRIANGLE_STRIP ) { - R_SetupFinalVert( &triv[vertcount], x, y, z, 0,0,0); - vertcount++; - if( vertcount == 3 ) + if( vertcount > 2 ) { + R_SetupFinalVert( &triv[(vertcount + 1) & 1 + 1], x, y, z, 0,0,0); R_RenderTriangle( triv ); - finalvert_t fv = triv[0]; - - triv[0] = triv[2]; - triv[2] = fv; - R_RenderTriangle( triv ); - fv = triv[0]; - triv[0] = triv[2]; - triv[2] = fv; - triv[0] = triv[1]; - triv[1] = triv[2]; - vertcount = 2; } + else + R_SetupFinalVert( &triv[vertcount], x, y, z, 0,0,0); + vertcount++; } } From dbabb861f2b0e38aa1ce3cde14ed16a681bd51dd Mon Sep 17 00:00:00 2001 From: mittorn Date: Tue, 26 Mar 2019 16:39:16 +0700 Subject: [PATCH 027/115] ref_soft: studiomodel texturing, finally fix TRIANGLE_STRIP --- r_local.h | 2 +- r_polyse.c | 8 ++++---- r_studio.c | 5 +++++ r_trialias.c | 14 +++++++------- r_triapi.c | 51 ++++++++++++++++++++++++++++++++++++++++----------- 5 files changed, 57 insertions(+), 23 deletions(-) diff --git a/r_local.h b/r_local.h index 2e6f296c..1d482b77 100644 --- a/r_local.h +++ b/r_local.h @@ -1329,7 +1329,7 @@ void R_RenderFace (msurface_t *fa, int clipflags); void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]); -void R_RenderTriangle( finalvert_t *pfv ); +void R_RenderTriangle( finalvert_t *fv1 , finalvert_t *fv2, finalvert_t *fv3 ); void R_SetupFinalVert( finalvert_t *fv, float x, float y, float z, int light, int s, int t ); // diff --git a/r_polyse.c b/r_polyse.c index c71e82d4..9c760472 100644 --- a/r_polyse.c +++ b/r_polyse.c @@ -1170,7 +1170,7 @@ void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) { int lsfrac, ltfrac; pixel_t *lpdest; - byte *lptex; + pixel_t *lptex; int llight; int lzi; short *lpz; @@ -1191,7 +1191,7 @@ void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) /*if(r_newrefdef.rdflags & RDF_IRGOGGLES && RI.currententity->flags & RF_IR_VISIBLE) *lpdest = ((byte *)vid.colormap)[irtable[*lptex]]; else*/ - *lpdest = color; //((byte *)vid.colormap)[*lptex + (llight & 0xFF00)]; + *lpdest = *lptex; //((byte *)vid.colormap)[*lptex + (llight & 0xFF00)]; //PGM *lpz = lzi >> 16; } @@ -1253,7 +1253,7 @@ void R_RasterizeAliasPolySmooth (void) ystart = plefttop[1]; d_aspancount = plefttop[0] - prighttop[0]; - d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) + + d_ptex = (pixel_t*)r_affinetridesc.pskin + (plefttop[2] >> 16) + (plefttop[3] >> 16) * r_affinetridesc.skinwidth; //#if id386ALIAS #if id386 @@ -1398,7 +1398,7 @@ void R_RasterizeAliasPolySmooth (void) ystart = plefttop[1]; d_aspancount = plefttop[0] - prighttop[0]; - d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) + + d_ptex = (pixel_t*)r_affinetridesc.pskin + (plefttop[2] >> 16) + (plefttop[3] >> 16) * r_affinetridesc.skinwidth; d_sfrac = 0; d_tfrac = 0; diff --git a/r_studio.c b/r_studio.c index 29974842..f5284af8 100644 --- a/r_studio.c +++ b/r_studio.c @@ -1813,6 +1813,7 @@ R_StudioSetupSkin static void R_StudioSetupSkin( studiohdr_t *ptexturehdr, int index ) { mstudiotexture_t *ptexture = NULL; + image_t *image; if( FBitSet( g_nForceFaceFlags, STUDIO_NF_CHROME )) return; @@ -1827,6 +1828,10 @@ static void R_StudioSetupSkin( studiohdr_t *ptexturehdr, int index ) if( r_lightmap->value && !r_fullbright->value ) GL_Bind( XASH_TEXTURE0, tr.whiteTexture ); else GL_Bind( XASH_TEXTURE0, ptexture[index].index ); + image = R_GetTexture(ptexture[index].index); + r_affinetridesc.pskin = image->pixels[0]; + r_affinetridesc.skinwidth = image->width; + r_affinetridesc.skinheight = image->height; } /* diff --git a/r_trialias.c b/r_trialias.c index 5616da31..fdd0778d 100644 --- a/r_trialias.c +++ b/r_trialias.c @@ -205,23 +205,23 @@ void R_SetupFinalVert( finalvert_t *fv, float x, float y, float z, int light, in fv->t = t << 16; } -void R_RenderTriangle( finalvert_t *pfv ) +void R_RenderTriangle( finalvert_t *fv1, finalvert_t *fv2, finalvert_t *fv3 ) { - if ( pfv[0].flags & pfv[1].flags & pfv[2].flags ) + if ( fv1->flags & fv2->flags & fv3->flags ) return ; // completely clipped - if ( ! (pfv[0].flags | pfv[1].flags | pfv[2].flags) ) + if ( ! (fv1->flags | fv2->flags | fv3->flags) ) { // totally unclipped - aliastriangleparms.a = &pfv[0]; - aliastriangleparms.b = &pfv[1]; - aliastriangleparms.c = &pfv[2]; + aliastriangleparms.a = fv1; + aliastriangleparms.b = fv2; + aliastriangleparms.c = fv3; R_DrawTriangle(); } else { // partially clipped - R_AliasClipTriangle (&pfv[0], &pfv[1], &pfv[2]); + R_AliasClipTriangle (fv1, fv2, fv3); } } diff --git a/r_triapi.c b/r_triapi.c index 15011d4b..cee0ae47 100644 --- a/r_triapi.c +++ b/r_triapi.c @@ -24,8 +24,9 @@ static struct } ds; finalvert_t triv[3]; -int vertcount; +int vertcount, n; int mode; +short s,t; /* =============================================================== @@ -115,7 +116,7 @@ void TriBegin( int mode1 ) pglBegin( mode ); #endif mode = mode1; - vertcount = 0; + vertcount = n = vertcount = 0; } /* @@ -128,7 +129,6 @@ draw triangle sequence void TriEnd( void ) { //if( vertcount == 3 ) - R_RenderTriangle( triv ); //pglEnd( ); } @@ -209,6 +209,8 @@ TriTexCoord2f void TriTexCoord2f( float u, float v ) { //pglTexCoord2f( u, v ); + s = r_affinetridesc.skinwidth * u; + t = r_affinetridesc.skinheight * v; } /* @@ -233,26 +235,53 @@ void TriVertex3f( float x, float y, float z ) { if( mode == TRI_TRIANGLE_FAN ) { - R_SetupFinalVert( &triv[vertcount], x, y, z, 0,0,0); + R_SetupFinalVert( &triv[vertcount], x, y, z, 0,s,t); vertcount++; if( vertcount >= 3 ) { - R_RenderTriangle( triv ); + R_RenderTriangle( &triv[0], &triv[1], &triv[2] ); triv[1] = triv[2]; vertcount = 2; } } if( mode == TRI_TRIANGLE_STRIP ) { - if( vertcount > 2 ) + R_SetupFinalVert( &triv[n], x, y, z, 0,s,t); + n++; + vertcount++; + if( n == 3 ) + n = 0; + if (vertcount >= 3) { - R_SetupFinalVert( &triv[(vertcount + 1) & 1 + 1], x, y, z, 0,0,0); - R_RenderTriangle( triv ); + if( vertcount & 1 ) + R_RenderTriangle( &triv[0], &triv[1], &triv[2] ); + else + R_RenderTriangle( &triv[2], &triv[1], &triv[0] ); } - else - R_SetupFinalVert( &triv[vertcount], x, y, z, 0,0,0); - vertcount++; } +#if 0 + if( mode == TRI_TRIANGLE_STRIP ) + { + R_SetupFinalVert( &triv[vertcount], x, y, z, 0,s,t); + vertcount++; + if( vertcount == 3 ) + { + + R_RenderTriangle( triv ); + finalvert_t fv = triv[0]; + + triv[0] = triv[2]; + triv[2] = fv; + R_RenderTriangle( triv ); + fv = triv[0]; + triv[0] = triv[2]; + triv[2] = fv; + triv[0] = triv[1]; + triv[1] = triv[2]; + vertcount = 2; + } + } +#endif } /* From 35e42a22951181da059a5ac666b39bd77073a760 Mon Sep 17 00:00:00 2001 From: mittorn Date: Tue, 26 Mar 2019 22:57:34 +0700 Subject: [PATCH 028/115] ref_soft: Viewmodel support --- r_local.h | 5 +++-- r_main.c | 8 ++++---- r_studio.c | 4 ++-- r_trialias.c | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/r_local.h b/r_local.h index 1d482b77..209f4e26 100644 --- a/r_local.h +++ b/r_local.h @@ -640,8 +640,8 @@ void Mod_SpriteUnloadTextures( void *data ); void Mod_UnloadAliasModel( struct model_s *mod ); void Mod_AliasUnloadTextures( void *data ); void GL_SetRenderMode( int mode ); -//void R_RunViewmodelEvents( void ); -//void R_DrawViewModel( void ); +void R_RunViewmodelEvents( void ); +void R_DrawViewModel( void ); int R_GetSpriteTexture( const struct model_s *m_pSpriteModel, int frame ); void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale ); void R_RemoveEfrags( struct cl_entity_s *ent ); @@ -1267,6 +1267,7 @@ extern aliastriangleparms_t aliastriangleparms; extern int r_aliasblendcolor; extern float aliasxscale, aliasyscale, aliasxcenter, aliasycenter; +extern float s_ziscale; void R_DrawTriangle( void ); //void R_DrawTriangle (finalvert_t *index0, finalvert_t *index1, finalvert_t *index2); diff --git a/r_main.c b/r_main.c index f3f0ad9d..3993f12a 100644 --- a/r_main.c +++ b/r_main.c @@ -1149,8 +1149,8 @@ void R_DrawEntitiesOnList( void ) // pglDisable( GL_BLEND ); // Trinity Render issues - //if( !RI.onlyClientDraw ) - //R_DrawViewModel(); + if( !RI.onlyClientDraw ) + R_DrawViewModel(); gEngfuncs.CL_ExtraUpdate(); //GL_CheckForErrors(); @@ -1766,8 +1766,8 @@ int R_RenderFrame( const ref_viewpass_t *rvp ) } tr.fCustomRendering = false; -// if( !RI.onlyClientDraw ) - // R_RunViewmodelEvents(); + if( !RI.onlyClientDraw ) + R_RunViewmodelEvents(); tr.realframecount++; // right called after viewmodel events R_RenderScene(); diff --git a/r_studio.c b/r_studio.c index f5284af8..22e25915 100644 --- a/r_studio.c +++ b/r_studio.c @@ -3477,7 +3477,7 @@ void R_DrawViewModel( void ) // adjust the depth range to prevent view model from poking into walls //pglDepthRange( gldepthmin, gldepthmin + 0.3f * ( gldepthmax - gldepthmin )); - /// TODO: ziscale + s_ziscale = (float)0x8000 * (float)0x10000 * 3.0; RI.currentmodel = RI.currententity->model; // backface culling for left-handed weapons @@ -3500,7 +3500,7 @@ void R_DrawViewModel( void ) // restore depth range //pglDepthRange( gldepthmin, gldepthmax ); - /// ziscale + s_ziscale = (float)0x8000 * (float)0x10000; // backface culling for left-handed weapons if( R_AllowFlipViewModel( RI.currententity ) || g_iBackFaceCull ) diff --git a/r_trialias.c b/r_trialias.c index fdd0778d..0233dda3 100644 --- a/r_trialias.c +++ b/r_trialias.c @@ -19,7 +19,7 @@ float aliastransform[3][4]; float aliasworldtransform[3][4]; float aliasoldworldtransform[3][4]; -static float s_ziscale; +float s_ziscale; static vec3_t s_alias_forward, s_alias_right, s_alias_up; From b35415637b47f4cefaa1abcbed109a10a381ceeb Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 27 Mar 2019 17:53:42 +0700 Subject: [PATCH 029/115] ref_soft: colormap support, basic studiomodel lighting --- r_draw.c | 3 +++ r_glblit.c | 32 ++++++++++++++++++++++++++++++++ r_light.c | 2 ++ r_local.h | 3 ++- r_main.c | 24 ++++++++++++++++-------- r_polyse.c | 15 +++++++++++---- r_studio.c | 1 + r_triapi.c | 17 +++++++++++++---- 8 files changed, 80 insertions(+), 17 deletions(-) diff --git a/r_draw.c b/r_draw.c index 2f6fb211..bffd94b0 100644 --- a/r_draw.c +++ b/r_draw.c @@ -299,6 +299,9 @@ R_Set2DMode void R_Set2DMode( qboolean enable ) { vid.color = COLOR_WHITE; + vid.is2d = enable; + vid.alpha = 7; + if( enable ) { // if( glState.in2DMode ) diff --git a/r_glblit.c b/r_glblit.c index 7b57a68e..20b33ca5 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -133,6 +133,7 @@ void R_BuildBlendMaps() { unsigned int r1, g1, b1; unsigned int r2, g2, b2; + unsigned int i, j; FOR_EACH_COLOR(1)FOR_EACH_COLOR(2) { @@ -169,6 +170,37 @@ void R_BuildBlendMaps() } } + for( i = 0; i < 8192; i++ ) + { + unsigned int r, g, b; + uint color = i << 3; + uint m = color >> 8; + uint j = color & 0xff; + + r1 = ((m >> (8 - 3) )<< 2 ) & MASK(5); + g1 = ((m >> (8 - 3 - 3)) << 3) & MASK(6); + b1 = ((m >> (8 - 3 - 3 - 2)) << 3) & MASK(5); + r1 |= MOVE_BIT(j, 5, 1) | MOVE_BIT(j, 2, 0); + g1 |= MOVE_BIT(j, 7, 2) | MOVE_BIT(j, 4, 1) | MOVE_BIT(j, 1, 0); + b1 |= MOVE_BIT(j, 6, 2) | MOVE_BIT(j, 3, 1) | MOVE_BIT(j, 0, 0); + + + unsigned short index1 = i; + for( j = 0; j < 32; j++) + { + unsigned int index2 = j << 13; + unsigned int major, minor; + r = r1 * j / 32; + g = g1 * j / 32; + b = b1 * j / 32; + major = (((r >> 2) & MASK(3)) << 5) |( (( (g >> 3) & MASK(3)) << 2 ) )| (((b >> 3) & MASK(2))); + + // save minor GBRGBRGB + minor = MOVE_BIT(r,1,5) | MOVE_BIT(r,0,2) | MOVE_BIT(g,2,7) | MOVE_BIT(g,1,4) | MOVE_BIT(g,0,1) | MOVE_BIT(b,2,6)| MOVE_BIT(b,1,3)|MOVE_BIT(b,0,0); + + vid.colormap[index2|index1] = major << 8 | (minor & 0xFF); + } + } } void R_AllocScreen(); diff --git a/r_light.c b/r_light.c index 08bd4fe3..86157006 100644 --- a/r_light.c +++ b/r_light.c @@ -472,6 +472,8 @@ colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t { colorVec light = R_LightVecInternal( start, end, lspot, lvec ); + light.r = light.g = light.b = 255; + if( lspot != NULL && lvec != NULL ) // CVAR_TO_BOOL( r_lighting_extended ) && { // trying to get light from ceiling (but ignore gradient analyze) diff --git a/r_local.h b/r_local.h index 209f4e26..56c74af5 100644 --- a/r_local.h +++ b/r_local.h @@ -133,7 +133,7 @@ typedef struct vrect_s typedef struct { pixel_t *buffer; // invisible buffer - pixel_t *colormap; // 256 * VID_GRADES size + pixel_t colormap[32*8192]; // 8192 * light levels //pixel_t *alphamap; // 256 * 256 translucency map #ifdef SEPARATE_BLIT pixel_t screen_minor[256]; @@ -146,6 +146,7 @@ typedef struct byte modmap[256*256]; byte alphamap[8*256*256]; pixel_t color; + qboolean is2d; byte alpha; // maybe compute colormask for minor byte? diff --git a/r_main.c b/r_main.c index 3993f12a..d5b01986 100644 --- a/r_main.c +++ b/r_main.c @@ -517,6 +517,7 @@ R_SetupFrustum */ void R_SetupFrustum( void ) { + AngleVectors( RI.viewangles, RI.vforward, RI.vright, RI.vup ); #if 0 ref_overview_t *ov = gEngfuncs.GetOverviewParms(); @@ -1034,20 +1035,27 @@ void R_DrawEntitiesOnList( void ) //R_DrawAliasModel( RI.currententity ); break; case mod_studio: - //R_DrawStudioModel( RI.currententity ); - /*{finalvert_t fv[3]; + R_DrawStudioModel( RI.currententity ); + #if 0 + // gradient debug (for colormap testing) + {finalvert_t fv[3]; void R_AliasSetUpTransform (void); extern void (*d_pdrawspans)(void *); extern void R_PolysetFillSpans8 ( void * ); d_pdrawspans = R_PolysetFillSpans8; //RI.currententity = gEngfuncs.GetEntityByIndex(0); R_AliasSetUpTransform(); - R_SetupFinalVert( &fv[0], -10, -10, 5, 0, 0, 0); - R_SetupFinalVert( &fv[1], -10, 10, 10, 0, 0, 0); - R_SetupFinalVert( &fv[2], 10, 10, -10, 0, 0, 0); - R_RenderTriangle( &fv ); - }*/ - R_DrawStudioModel( RI.currententity ); + image_t *image = R_GetTexture(GL_LoadTexture("gfx/env/desertbk", NULL, 0, 0)); + r_affinetridesc.pskin = image->pixels[0]; + r_affinetridesc.skinwidth = image->width; + r_affinetridesc.skinheight = image->height; + R_SetupFinalVert( &fv[0], 0, -50, 50, 31 << 8, 0, 0); + R_SetupFinalVert( &fv[1], 0, 50, 50, 0 << 8, image->width, 0); + R_SetupFinalVert( &fv[2], 0, 0, 0, 0 << 8, image->width/2, image->height); + R_RenderTriangle( &fv[0], &fv[1], &fv[2] ); + } +#endif + break; default: diff --git a/r_polyse.c b/r_polyse.c index 9c760472..0852d2c5 100644 --- a/r_polyse.c +++ b/r_polyse.c @@ -1145,11 +1145,11 @@ void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) #else void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) { - int color; + //int color; int lcount; // FIXME: do z buffering - color = d_aflatcolor++ * 10; + //color = d_aflatcolor++ * 10; do { @@ -1191,8 +1191,15 @@ void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) /*if(r_newrefdef.rdflags & RDF_IRGOGGLES && RI.currententity->flags & RF_IR_VISIBLE) *lpdest = ((byte *)vid.colormap)[irtable[*lptex]]; else*/ - *lpdest = *lptex; //((byte *)vid.colormap)[*lptex + (llight & 0xFF00)]; -//PGM + //*lpdest = *lptex; //((byte *)vid.colormap)[*lptex + (llight & 0xFF00)]; + uint src = *lptex; + //*lpdest = //vid.colormap[src & 0xff00|(llight>>8)] << 8 | (src & llight & 0xff) | ((src & 0xff) >> 3); + // very dirty, maybe need dual colormap? + //*lpdest = (vid.colormap[src >> 8 | (llight & 0xFF00)] << 8) | src & 0xff; + // 13 bit lighting, 32 light levels + *lpdest = vid.colormap[(src >> 3) | ((llight & 0x1F00) << 5)] | src & 7; + + //PGM *lpz = lzi >> 16; } lpdest++; diff --git a/r_studio.c b/r_studio.c index 22e25915..48b2e623 100644 --- a/r_studio.c +++ b/r_studio.c @@ -1770,6 +1770,7 @@ static void R_StudioSetColorBegin(short *ptricmds, vec3_t *pstudionorms ) color[3] = tr.blend * 255; VectorCopy( (byte*)&RI.currententity->curstate.rendercolor, color ); //pglColor4ubv( color ); + TriColor4ub(color[0], color[1], color[2], color[3]); } else _TriColor4f( lv[0], lv[1], lv[2], tr.blend ); } diff --git a/r_triapi.c b/r_triapi.c index cee0ae47..922fbe54 100644 --- a/r_triapi.c +++ b/r_triapi.c @@ -27,6 +27,7 @@ finalvert_t triv[3]; int vertcount, n; int mode; short s,t; +uint light; /* =============================================================== @@ -145,17 +146,25 @@ void _TriColor4f( float rr, float gg, float bb, float aa ) unsigned int major, minor; + + //gEngfuncs.Con_Printf("%d\n", vid.alpha); + + light = (rr + gg + bb) * 31 / 3; + if( light > 31 ) + light = 31; + + if( !vid.is2d ) + return; + vid.alpha = aa * 7; if( vid.alpha > 7 ) vid.alpha = 7; - //gEngfuncs.Con_Printf("%d\n", vid.alpha); if( rr == 1 && gg == 1 && bb == 1 ) { vid.color = COLOR_WHITE; return; } - r = rr * 31, g = gg * 63, b = bb * 31; @@ -235,7 +244,7 @@ void TriVertex3f( float x, float y, float z ) { if( mode == TRI_TRIANGLE_FAN ) { - R_SetupFinalVert( &triv[vertcount], x, y, z, 0,s,t); + R_SetupFinalVert( &triv[vertcount], x, y, z, light << 8,s,t); vertcount++; if( vertcount >= 3 ) { @@ -246,7 +255,7 @@ void TriVertex3f( float x, float y, float z ) } if( mode == TRI_TRIANGLE_STRIP ) { - R_SetupFinalVert( &triv[n], x, y, z, 0,s,t); + R_SetupFinalVert( &triv[n], x, y, z, light << 8,s,t); n++; vertcount++; if( n == 3 ) From 529bb53d526a938f7de2b65e65185ee97ebe743e Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 27 Mar 2019 19:57:37 +0700 Subject: [PATCH 030/115] ref_soft: Static quake-based lightmap (does not work with extended bsp) --- r_light.c | 2 +- r_surf.c | 258 ++++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 223 insertions(+), 37 deletions(-) diff --git a/r_light.c b/r_light.c index 86157006..6d17f51c 100644 --- a/r_light.c +++ b/r_light.c @@ -20,7 +20,7 @@ GNU General Public License for more details. #include "ref_params.h" //unused, need refactor -unsigned blocklights[1024]; +unsigned blocklights[10240]; /* ============================================================================= diff --git a/r_surf.c b/r_surf.c index 9a12c409..e41c939e 100644 --- a/r_surf.c +++ b/r_surf.c @@ -48,8 +48,8 @@ static void (*surfmiptable[4])(void) = { R_DrawSurfaceBlock8_mip3 }; -void R_BuildLightMap (void); -extern unsigned blocklights[1024]; // allow some very large lightmaps +//void R_BuildLightMap (void); +extern unsigned blocklights[10240]; // allow some very large lightmaps float surfscale; qboolean r_cache_thrash; // set if surface cache is thrashing @@ -59,6 +59,188 @@ surfcache_t *sc_rover, *sc_base; static int rtable[MOD_FRAMES][MOD_FRAMES]; +#if 0 +/* +================= +R_BuildLightmap + +Combine and scale multiple lightmaps into the floating +format in r_blocklights +================= +*/ +static void R_BuildLightMap( ) +{ + int smax, tmax; + uint *bl, scale; + int i, map, size, s, t; + int sample_size; + msurface_t *surf = r_drawsurf.surf; + mextrasurf_t *info = surf->info; + color24 *lm; + qboolean dynamic = 0; + + //sample_size = gEngfuncs.Mod_SampleSizeForFace( surf ); + //smax = ( info->lightextents[0] / sample_size ) + 1; + //tmax = ( info->lightextents[1] / sample_size ) + 1; + + smax = (surf->extents[0]>>4)+1; + tmax = (surf->extents[1]>>4)+1; + + size = smax * tmax; + + lm = surf->samples; + + memset( blocklights, 0, sizeof( uint ) * size ); + + // add all the lightmaps + for( map = 0; map < MAXLIGHTMAPS; map++ ) + { + scale = tr.lightstylevalue[surf->styles[map]]; + + for( i = 0, bl = blocklights; i < size; i++, bl += 1, lm++ ) + { + bl[0] += lm->r; + bl[0] += lm->g; + bl[0] += lm->b; + + //printf("test\n"); + //bl[1] += gEngfuncs.LightToTexGamma( lm->g ) * scale; + //bl[2] += gEngfuncs.LightToTexGamma( lm->b ) * scale; + } + } + + // add all the dynamic lights + //if( surf->dlightframe == tr.framecount && dynamic ) + //R_AddDynamicLights( surf ); + + // Put into texture format + //stride -= (smax << 2); + //bl = blocklights; + + /*for( t = 0; t < tmax; t++, dest += stride ) + { + for( s = 0; s < smax; s++ ) + { + dest[0] = Q_min((bl[0] >> 7), 255 ); + //dest[1] = Q_min((bl[1] >> 7), 255 ); + //dest[2] = Q_min((bl[2] >> 7), 255 ); + //dest[3] = 255; + + bl += 3; + dest += 4; + } + }*/ + // bound, invert, and shift + for (i=0 ; i 767 ) + t = 767; + t = t * 31 / 256 / 3;//(255*256 - t) >> (8 - VID_CBITS); + + //if (t < (1 << 6)) + //t = (1 << 6); + t = t << 8; + + blocklights[i] = t; + } +} +#else + +/* +=============== +R_BuildLightMap + +Combine and scale multiple lightmaps into the 8.8 format in blocklights +=============== +*/ +void R_BuildLightMap (void) +{ + int smax, tmax; + int t; + int i, size; + byte *lightmap; + unsigned scale; + int maps; + msurface_t *surf; + + surf = r_drawsurf.surf; + + //smax = (surf->extents[0]>>4)+1; + //tmax = (surf->extents[1]>>4)+1; + mextrasurf_t *info = surf->info; + int sample_size = gEngfuncs.Mod_SampleSizeForFace( surf ); + smax = ( info->lightextents[0] / sample_size ) + 1; + tmax = ( info->lightextents[1] / sample_size ) + 1; + + size = smax*tmax; + + if (r_fullbright->value ) + { + for (i=0 ; isamples; + if (lightmap) + for (maps = 0 ; maps < MAXLIGHTMAPS && surf->styles[maps] != 255 ; + maps++) + { + scale = r_drawsurf.lightadj[maps]; // 8.8 fraction + for (i=0 ; idlightframe == r_framecount) + //R_AddDynamicLights (); + +// bound, invert, and shift + /*for (i=0 ; i> (8 - VID_CBITS); + + if (t < (1 << 6)) + t = (1 << 6); + + blocklights[i] = t; + }*/ + for (i=0 ; i 767 ) + t = 767; + t = t * 31 / 256/3;//(255*256 - t) >> (8 - VID_CBITS); + + //if (t < (1 << 6)) + //t = (1 << 6); + t = t << 8; + + blocklights[i] = t; + } +} + +#endif + void R_InitRandomTable( void ) { int tu, tv; @@ -211,7 +393,8 @@ void R_DrawSurface (void) blockdivshift = 4 - r_drawsurf.surfmip; blockdivmask = (1 << blockdivshift) - 1; - r_lightwidth = (r_drawsurf.surf->extents[0]>>4)+1; + r_lightwidth = ( r_drawsurf.surf->info->lightextents[0] / gEngfuncs.Mod_SampleSizeForFace( r_drawsurf.surf ) ) + 1; + //r_lightwidth = (r_drawsurf.surf->extents[0]>>4)+1; r_numhblocks = r_drawsurf.surfwidth >> blockdivshift; r_numvblocks = r_drawsurf.surfheight >> blockdivshift; @@ -264,6 +447,7 @@ void R_DrawSurface (void) //============================================================================= #if !id386 +#define BLEND_LM(pix, light) vid.colormap[(pix >> 3) | ((light & 0x1f00) << 5)] | pix & 7; /* ================ @@ -282,11 +466,11 @@ void R_DrawSurfaceBlock8_mip0 (void) { // FIXME: make these locals? // FIXME: use delta rather than both right and left, like ASM? - //lightleft = r_lightptr[0]; - //lightright = r_lightptr[1]; - //r_lightptr += r_lightwidth; - //lightleftstep = (r_lightptr[0] - lightleft) >> 4; - //lightrightstep = (r_lightptr[1] - lightright) >> 4; + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 4; + lightrightstep = (r_lightptr[1] - lightright) >> 4; for (i=0 ; i<16 ; i++) { @@ -298,15 +482,17 @@ void R_DrawSurfaceBlock8_mip0 (void) for (b=15; b>=0; b--) { pix = psource[b]; - prowdest[b] = pix; + prowdest[b] = BLEND_LM(pix, light); + + // pix; //((unsigned char *)vid.colormap) //[(light & 0xFF00) + pix]; light += lightstep; } psource += sourcetstep; - //lightright += lightrightstep; - //lightleft += lightleftstep; + lightright += lightrightstep; + lightleft += lightleftstep; prowdest += surfrowbytes; } @@ -333,11 +519,11 @@ void R_DrawSurfaceBlock8_mip1 (void) { // FIXME: make these locals? // FIXME: use delta rather than both right and left, like ASM? - //lightleft = r_lightptr[0]; - //lightright = r_lightptr[1]; - //r_lightptr += r_lightwidth; - //lightleftstep = (r_lightptr[0] - lightleft) >> 3; - //lightrightstep = (r_lightptr[1] - lightright) >> 3; + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 3; + lightrightstep = (r_lightptr[1] - lightright) >> 3; for (i=0 ; i<8 ; i++) { @@ -349,15 +535,15 @@ void R_DrawSurfaceBlock8_mip1 (void) for (b=7; b>=0; b--) { pix = psource[b]; - prowdest[b] = pix; + prowdest[b] = BLEND_LM(pix, light); //((unsigned char *)vid.colormap) //[(light & 0xFF00) + pix]; light += lightstep; } psource += sourcetstep; - //lightright += lightrightstep; - //lightleft += lightleftstep; + lightright += lightrightstep; + lightleft += lightleftstep; prowdest += surfrowbytes; } @@ -384,11 +570,11 @@ void R_DrawSurfaceBlock8_mip2 (void) { // FIXME: make these locals? // FIXME: use delta rather than both right and left, like ASM? - //lightleft = r_lightptr[0]; - //lightright = r_lightptr[1]; - //r_lightptr += r_lightwidth; - //lightleftstep = (r_lightptr[0] - lightleft) >> 2; - //lightrightstep = (r_lightptr[1] - lightright) >> 2; + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 2; + lightrightstep = (r_lightptr[1] - lightright) >> 2; for (i=0 ; i<4 ; i++) { @@ -400,15 +586,15 @@ void R_DrawSurfaceBlock8_mip2 (void) for (b=3; b>=0; b--) { pix = psource[b]; - prowdest[b] = pix; + prowdest[b] = BLEND_LM(pix, light);; //((unsigned char *)vid.colormap) //[(light & 0xFF00) + pix]; light += lightstep; } psource += sourcetstep; - //lightright += lightrightstep; - //lightleft += lightleftstep; + lightright += lightrightstep; + lightleft += lightleftstep; prowdest += surfrowbytes; } @@ -435,11 +621,11 @@ void R_DrawSurfaceBlock8_mip3 (void) { // FIXME: make these locals? // FIXME: use delta rather than both right and left, like ASM? - //lightleft = r_lightptr[0]; - //lightright = r_lightptr[1]; - //r_lightptr += r_lightwidth; - //lightleftstep = (r_lightptr[0] - lightleft) >> 1; - //lightrightstep = (r_lightptr[1] - lightright) >> 1; + lightleft = r_lightptr[0]; + lightright = r_lightptr[1]; + r_lightptr += r_lightwidth; + lightleftstep = (r_lightptr[0] - lightleft) >> 1; + lightrightstep = (r_lightptr[1] - lightright) >> 1; for (i=0 ; i<2 ; i++) { @@ -451,15 +637,15 @@ void R_DrawSurfaceBlock8_mip3 (void) for (b=1; b>=0; b--) { pix = psource[b]; - prowdest[b] = pix; + prowdest[b] = BLEND_LM(pix, light);; //((unsigned char *)vid.colormap) //[(light & 0xFF00) + pix]; light += lightstep; } psource += sourcetstep; - //lightright += lightrightstep; - //lightleft += lightleftstep; + lightright += lightrightstep; + lightleft += lightleftstep; prowdest += surfrowbytes; } @@ -752,7 +938,7 @@ surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) c_surf++; // calculate the lightings - //R_BuildLightMap (); + R_BuildLightMap ( ); // rasterize the surface into the cache R_DrawSurface (); From 44a8ede94d5bceda84e1000bee5e8a043418f109 Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 27 Mar 2019 20:17:58 +0700 Subject: [PATCH 031/115] ref_soft: Re-enable lightvec calculation --- r_light.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/r_light.c b/r_light.c index 6d17f51c..d1e22ee3 100644 --- a/r_light.c +++ b/r_light.c @@ -344,11 +344,11 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f, { uint scale = tr.lightstylevalue[surf->styles[map]]; - if( tr.ignore_lightgamma ) + if( 1 ) //tr.ignore_lightgamma ) { - cv->r += lm->r * scale; - cv->g += lm->g * scale; - cv->b += lm->b * scale; + cv->r += lm->r * 255 * 2.5; // scale; + cv->g += lm->g * 255 * 2.5; // scale; + cv->b += lm->b * 255 * 2.5; // scale; } else { @@ -472,7 +472,7 @@ colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t { colorVec light = R_LightVecInternal( start, end, lspot, lvec ); - light.r = light.g = light.b = 255; + //light.r = light.g = light.b = 255; if( lspot != NULL && lvec != NULL ) // CVAR_TO_BOOL( r_lighting_extended ) && { From 153b8cbcc364e0085c16d2722deee9e944554e7e Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 27 Mar 2019 21:09:44 +0700 Subject: [PATCH 032/115] ref_soft: Xash3D lightmaps and dynamic lighting (world only) --- r_light.c | 4 +- r_main.c | 3 +- r_surf.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 115 insertions(+), 15 deletions(-) diff --git a/r_light.c b/r_light.c index d1e22ee3..8f0e2331 100644 --- a/r_light.c +++ b/r_light.c @@ -131,10 +131,10 @@ void R_MarkLights( dlight_t *light, int bit, mnode_t *node ) if( !BoundsAndSphereIntersect( surf->info->mins, surf->info->maxs, light->origin, light->radius )) continue; // no intersection - if( surf->dlightframe != tr.dlightframecount ) + if( surf->dlightframe != r_framecount )//tr.dlightframecount ) { surf->dlightbits = 0; - surf->dlightframe = tr.dlightframecount; + surf->dlightframe = r_framecount; //tr.dlightframecount; } surf->dlightbits |= bit; } diff --git a/r_main.c b/r_main.c index d5b01986..d1941682 100644 --- a/r_main.c +++ b/r_main.c @@ -1611,10 +1611,11 @@ void R_RenderScene( void ) // begin a new frame tr.framecount++; - R_PushDlights(); R_SetupFrustum(); R_SetupFrame(); + + R_PushDlights(); // R_SetupGL( true ); R_Clear( ~0 ); diff --git a/r_surf.c b/r_surf.c index e41c939e..b3aa4748 100644 --- a/r_surf.c +++ b/r_surf.c @@ -59,7 +59,106 @@ surfcache_t *sc_rover, *sc_base; static int rtable[MOD_FRAMES][MOD_FRAMES]; -#if 0 +#if 1 + +static void R_BuildLightMap( ); +/* +=============== +R_AddDynamicLights +=============== +*/ +void R_AddDynamicLights( msurface_t *surf ) +{ + float dist, rad, minlight; + int lnum, s, t, sd, td, smax, tmax; + float sl, tl, sacc, tacc; + vec3_t impact, origin_l; + mextrasurf_t *info = surf->info; + int sample_frac = 1.0; + float sample_size; + mtexinfo_t *tex; + dlight_t *dl; + uint *bl; + + // no dlighted surfaces here + //if( !R_CountSurfaceDlights( surf )) return; + + sample_size = gEngfuncs.Mod_SampleSizeForFace( surf ); + smax = (info->lightextents[0] / sample_size) + 1; + tmax = (info->lightextents[1] / sample_size) + 1; + tex = surf->texinfo; + + if( FBitSet( tex->flags, TEX_WORLD_LUXELS )) + { + if( surf->texinfo->faceinfo ) + sample_frac = surf->texinfo->faceinfo->texture_step; + //else if( FBitSet( surf->texinfo->flags, TEX_EXTRA_LIGHTMAP )) + // sample_frac = LM_SAMPLE_EXTRASIZE; + else sample_frac = LM_SAMPLE_SIZE; + } + + for( lnum = 0; lnum < MAX_DLIGHTS; lnum++ ) + { + if( !FBitSet( surf->dlightbits, BIT( lnum ))) + continue; // not lit by this light + + dl = gEngfuncs.GetDynamicLight( lnum ); + + // transform light origin to local bmodel space + //if( !tr.modelviewIdentity ) + //Matrix4x4_VectorITransform( RI.objectMatrix, dl->origin, origin_l ); + //else + VectorCopy( dl->origin, origin_l ); + + rad = dl->radius; + dist = PlaneDiff( origin_l, surf->plane ); + rad -= fabs( dist ); + + // rad is now the highest intensity on the plane + minlight = dl->minlight; + if( rad < minlight ) + continue; + + minlight = rad - minlight; + + if( surf->plane->type < 3 ) + { + VectorCopy( origin_l, impact ); + impact[surf->plane->type] -= dist; + } + else VectorMA( origin_l, -dist, surf->plane->normal, impact ); + + sl = DotProduct( impact, info->lmvecs[0] ) + info->lmvecs[0][3] - info->lightmapmins[0]; + tl = DotProduct( impact, info->lmvecs[1] ) + info->lmvecs[1][3] - info->lightmapmins[1]; + bl = blocklights; + + for( t = 0, tacc = 0; t < tmax; t++, tacc += sample_size ) + { + td = (tl - tacc) * sample_frac; + if( td < 0 ) td = -td; + + for( s = 0, sacc = 0; s < smax; s++, sacc += sample_size, bl += 1 ) + { + sd = (sl - sacc) * sample_frac; + if( sd < 0 ) sd = -sd; + + if( sd > td ) dist = sd + (td >> 1); + else dist = td + (sd >> 1); + + if( dist < minlight ) + { + printf("dlight %f\n", dist); + //*(void**)0 = 0; + bl[0] += ((int)((rad - dist) * 256) * 7.5) / 256; + //bl[1] += ((int)((rad - dist) * 256) * 2.5) / 256; + //bl[2] += ((int)((rad - dist) * 256) * 2.5) / 256; + } + } + } + } +} + + /* ================= R_BuildLightmap @@ -79,12 +178,12 @@ static void R_BuildLightMap( ) color24 *lm; qboolean dynamic = 0; - //sample_size = gEngfuncs.Mod_SampleSizeForFace( surf ); - //smax = ( info->lightextents[0] / sample_size ) + 1; - //tmax = ( info->lightextents[1] / sample_size ) + 1; + sample_size = gEngfuncs.Mod_SampleSizeForFace( surf ); + smax = ( info->lightextents[0] / sample_size ) + 1; + tmax = ( info->lightextents[1] / sample_size ) + 1; - smax = (surf->extents[0]>>4)+1; - tmax = (surf->extents[1]>>4)+1; + //smax = (surf->extents[0]>>4)+1; + //tmax = (surf->extents[1]>>4)+1; size = smax * tmax; @@ -93,15 +192,15 @@ static void R_BuildLightMap( ) memset( blocklights, 0, sizeof( uint ) * size ); // add all the lightmaps - for( map = 0; map < MAXLIGHTMAPS; map++ ) + for( map = 0; map < MAXLIGHTMAPS && surf->styles[map] != 255; map++ ) { scale = tr.lightstylevalue[surf->styles[map]]; for( i = 0, bl = blocklights; i < size; i++, bl += 1, lm++ ) { - bl[0] += lm->r; - bl[0] += lm->g; - bl[0] += lm->b; + bl[0] += lm->r * 2.5; + bl[0] += lm->g * 2.5; + bl[0] += lm->b * 2.5; //printf("test\n"); //bl[1] += gEngfuncs.LightToTexGamma( lm->g ) * scale; @@ -110,8 +209,8 @@ static void R_BuildLightMap( ) } // add all the dynamic lights - //if( surf->dlightframe == tr.framecount && dynamic ) - //R_AddDynamicLights( surf ); + if( surf->dlightframe == r_framecount ) + R_AddDynamicLights( surf ); // Put into texture format //stride -= (smax << 2); From 36a5247181e1625a66764a4653b2cdd21eccbb26 Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 27 Mar 2019 21:16:33 +0700 Subject: [PATCH 033/115] ref_soft: bmodel dlights (ignore transform) --- r_main.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/r_main.c b/r_main.c index d1941682..d58186c2 100644 --- a/r_main.c +++ b/r_main.c @@ -1334,6 +1334,7 @@ void R_DrawBEntitiesOnList (void) for( i = 0; i < tr.draw_list->num_solid_entities && !RI.onlyClientDraw; i++ ) { + int k; RI.currententity = tr.draw_list->solid_entities[i]; RI.currentmodel = RI.currententity->model; if (!RI.currentmodel) @@ -1388,6 +1389,22 @@ void R_DrawBEntitiesOnList (void) } }*/ + // calculate dynamic lighting for bmodel + for( k = 0; k < MAX_DLIGHTS; k++ ) + { + dlight_t *l = gEngfuncs.GetDynamicLight( k ); + + if( l->die < gpGlobals->time || !l->radius ) + continue; + + /*VectorCopy( l->origin, oldorigin ); // save lightorigin + Matrix4x4_VectorITransform( RI.objectMatrix, l->origin, origin_l ); + VectorCopy( origin_l, l->origin ); // move light in bmodel space + R_MarkLights( l, 1<nodes + clmodel->hulls[0].firstclipnode ); + VectorCopy( oldorigin, l->origin ); // restore lightorigin*/ + R_MarkLights( l, 1<nodes + RI.currentmodel->hulls[0].firstclipnode ); + } + // RI.currentmodel = tr.draw_list->solid_entities[i]->model; // RI.currententity = tr.draw_list->solid_entities[i]; RI.currententity->topnode = topnode; From 6eae7acd34e595f812dfbe0fa9f97be47d3b5054 Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 27 Mar 2019 21:34:37 +0700 Subject: [PATCH 034/115] ref_soft: lightstyle support --- r_context.c | 2 +- r_surf.c | 27 ++++++++++++++++++++------- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/r_context.c b/r_context.c index 6291680b..1df68953 100644 --- a/r_context.c +++ b/r_context.c @@ -495,7 +495,7 @@ void CL_DrawParticlesExternal(const ref_viewpass_t *rvp, qboolean trans_pass, fl void GL_BuildLightmaps() { - + CL_RunLightStyles(); } void Mod_SetOrthoBounds(const float *mins, const float *maxs) diff --git a/r_surf.c b/r_surf.c index b3aa4748..784ca161 100644 --- a/r_surf.c +++ b/r_surf.c @@ -198,9 +198,9 @@ static void R_BuildLightMap( ) for( i = 0, bl = blocklights; i < size; i++, bl += 1, lm++ ) { - bl[0] += lm->r * 2.5; - bl[0] += lm->g * 2.5; - bl[0] += lm->b * 2.5; + bl[0] += lm->r * scale * 2.5; + bl[0] += lm->g * scale * 2.5; + bl[0] += lm->b * scale * 2.5; //printf("test\n"); //bl[1] += gEngfuncs.LightToTexGamma( lm->g ) * scale; @@ -235,9 +235,9 @@ static void R_BuildLightMap( ) t = (int)blocklights[i]; if (t < 0) t = 0; - if( t > 767 ) - t = 767; - t = t * 31 / 256 / 3;//(255*256 - t) >> (8 - VID_CBITS); + if( t > 65535 * 3 ) + t = 65535 * 3; + t = t * 31 / 65535 / 3;//(255*256 - t) >> (8 - VID_CBITS); //if (t < (1 << 6)) //t = (1 << 6); @@ -970,6 +970,7 @@ D_CacheSurface surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) { surfcache_t *cache; + int maps; // // if the surface is animating or flashing, flush the cache // @@ -986,6 +987,15 @@ surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) // cache = CACHESPOT(surface)[miplevel]; + // check for lightmap modification + for( maps = 0; maps < MAXLIGHTMAPS && surface->styles[maps] != 255; maps++ ) + { + if( tr.lightstylevalue[surface->styles[maps]] != surface->cached_light[maps] ) + { + surface->dlightframe = r_framecount; + } + } + if (cache && !cache->dlight && surface->dlightframe != r_framecount && cache->image == r_drawsurf.image @@ -1028,7 +1038,10 @@ surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) cache->lightadj[1] = r_drawsurf.lightadj[1]; cache->lightadj[2] = r_drawsurf.lightadj[2]; cache->lightadj[3] = r_drawsurf.lightadj[3]; - + for( maps = 0; maps < MAXLIGHTMAPS && surface->styles[maps] != 255; maps++ ) + { + surface->cached_light[maps] = tr.lightstylevalue[surface->styles[maps]]; + } // // draw and light the surface texture // From 1871f39b2bce1ae9aa295035f49a2c88fbf28cf2 Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 28 Mar 2019 02:05:19 +0700 Subject: [PATCH 035/115] ref_soft: Decals support --- r_context.c | 31 -- r_decals.c | 1296 +++++++++++++++++++++++++++++++++++++++++++++++++++ r_local.h | 10 +- r_main.c | 4 +- r_surf.c | 128 ++++- 5 files changed, 1430 insertions(+), 39 deletions(-) create mode 100644 r_decals.c diff --git a/r_context.c b/r_context.c index 1df68953..9e3f0307 100644 --- a/r_context.c +++ b/r_context.c @@ -387,27 +387,6 @@ qboolean VID_CubemapShot(const char *base, uint size, const float *vieworg, qboo // cubemaps? in my softrender??? } -void R_DecalShoot(int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale) -{ - -} - -void R_DecalRemoveAll(int texture) -{ - -} - -int R_CreateDecalList(decallist_t *pList) -{ - return 0; -} - -void R_ClearAllDecals() -{ - -} - - void R_InitSkyClouds(mip_t *mt, texture_t *tx, qboolean custom_palette) { @@ -448,16 +427,6 @@ void DrawSingleDecal(decal_t *pDecal, msurface_t *fa) } -float *R_DecalSetupVerts(decal_t *pDecal, msurface_t *surf, int texture, int *outCount) -{ - return NULL; -} - -void R_EntityRemoveDecals(model_t *mod) -{ - -} - void GL_SelectTexture(int texture) { diff --git a/r_decals.c b/r_decals.c new file mode 100644 index 00000000..f3fd318d --- /dev/null +++ b/r_decals.c @@ -0,0 +1,1296 @@ +/* +gl_decals.c - decal paste and rendering +Copyright (C) 2010 Uncle Mike + +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 3 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. +*/ + +#include "r_local.h" +//#include "cl_tent.h" + +#define DECAL_OVERLAP_DISTANCE 2 +#define DECAL_DISTANCE 4 // too big values produce more clipped polygons +#define MAX_DECALCLIPVERT 32 // produced vertexes of fragmented decal +#define DECAL_CACHEENTRY 256 // MUST BE POWER OF 2 or code below needs to change! +#define DECAL_TRANSPARENT_THRESHOLD 230 // transparent decals draw with GL_MODULATE + +// empirically determined constants for minimizing overalpping decals +#define MAX_OVERLAP_DECALS 6 +#define DECAL_OVERLAP_DIST 8 +#define MIN_DECAL_SCALE 0.01f +#define MAX_DECAL_SCALE 16.0f + +// clip edges +#define LEFT_EDGE 0 +#define RIGHT_EDGE 1 +#define TOP_EDGE 2 +#define BOTTOM_EDGE 3 + +// This structure contains the information used to create new decals +typedef struct +{ + vec3_t m_Position; // world coordinates of the decal center + model_t *m_pModel; // the model the decal is going to be applied in + int m_iTexture; // The decal material + int m_Size; // Size of the decal (in world coords) + int m_Flags; + int m_Entity; // Entity the decal is applied to. + float m_scale; + int m_decalWidth; + int m_decalHeight; + vec3_t m_Basis[3]; +} decalinfo_t; + +static float g_DecalClipVerts[MAX_DECALCLIPVERT][VERTEXSIZE]; +static float g_DecalClipVerts2[MAX_DECALCLIPVERT][VERTEXSIZE]; + +decal_t gDecalPool[MAX_RENDER_DECALS]; +static int gDecalCount; + +void R_ClearDecals( void ) +{ + memset( gDecalPool, 0, sizeof( gDecalPool )); + gDecalCount = 0; +} + +// unlink pdecal from any surface it's attached to +static void R_DecalUnlink( decal_t *pdecal ) +{ + decal_t *tmp; + + if( pdecal->psurface ) + { + if( pdecal->psurface->pdecals == pdecal ) + { + pdecal->psurface->pdecals = pdecal->pnext; + } + else + { + tmp = pdecal->psurface->pdecals; + if( !tmp ) gEngfuncs.Host_Error( "D_DecalUnlink: bad decal list\n" ); + + while( tmp->pnext ) + { + if( tmp->pnext == pdecal ) + { + tmp->pnext = pdecal->pnext; + break; + } + tmp = tmp->pnext; + } + } + } + + if( pdecal->polys ) + Mem_Free( pdecal->polys ); + + pdecal->psurface = NULL; + pdecal->polys = NULL; +} + +// Just reuse next decal in list +// A decal that spans multiple surfaces will use multiple decal_t pool entries, +// as each surface needs it's own. +static decal_t *R_DecalAlloc( decal_t *pdecal ) +{ + int limit = MAX_RENDER_DECALS; + + if( r_decals->value < limit ) + limit = r_decals->value; + + if( !limit ) return NULL; + + if( !pdecal ) + { + int count = 0; + + // check for the odd possiblity of infinte loop + do + { + if( gDecalCount >= limit ) + gDecalCount = 0; + + pdecal = &gDecalPool[gDecalCount]; // reuse next decal + gDecalCount++; + count++; + } while( FBitSet( pdecal->flags, FDECAL_PERMANENT ) && count < limit ); + } + + // if decal is already linked to a surface, unlink it. + R_DecalUnlink( pdecal ); + + return pdecal; +} + +//----------------------------------------------------------------------------- +// find decal image and grab size from it +//----------------------------------------------------------------------------- +static void R_GetDecalDimensions( int texture, int *width, int *height ) +{ + if( width ) *width = 1; // to avoid divide by zero + if( height ) *height = 1; + + R_GetTextureParms( width, height, texture ); +} + +//----------------------------------------------------------------------------- +// compute the decal basis based on surface normal +//----------------------------------------------------------------------------- +void R_DecalComputeBasis( msurface_t *surf, int flags, vec3_t textureSpaceBasis[3] ) +{ + vec3_t surfaceNormal; + + // setup normal + if( surf->flags & SURF_PLANEBACK ) + VectorNegate( surf->plane->normal, surfaceNormal ); + else VectorCopy( surf->plane->normal, surfaceNormal ); + + VectorNormalize2( surfaceNormal, textureSpaceBasis[2] ); +#if 0 + if( FBitSet( flags, FDECAL_CUSTOM )) + { + vec3_t pSAxis = { 1, 0, 0 }; + + // T = S cross N + CrossProduct( pSAxis, textureSpaceBasis[2], textureSpaceBasis[1] ); + + // Name sure they aren't parallel or antiparallel + // In that case, fall back to the normal algorithm. + if( DotProduct( textureSpaceBasis[1], textureSpaceBasis[1] ) > 1e-6 ) + { + // S = N cross T + CrossProduct( textureSpaceBasis[2], textureSpaceBasis[1], textureSpaceBasis[0] ); + + VectorNormalizeFast( textureSpaceBasis[0] ); + VectorNormalizeFast( textureSpaceBasis[1] ); + return; + } + // Fall through to the standard algorithm for parallel or antiparallel + } +#endif + VectorNormalize2( surf->texinfo->vecs[0], textureSpaceBasis[0] ); + VectorNormalize2( surf->texinfo->vecs[1], textureSpaceBasis[1] ); +} + +void R_SetupDecalTextureSpaceBasis( decal_t *pDecal, msurface_t *surf, int texture, vec3_t textureSpaceBasis[3], float decalWorldScale[2] ) +{ + int width, height; + + // Compute the non-scaled decal basis + R_DecalComputeBasis( surf, pDecal->flags, textureSpaceBasis ); + R_GetDecalDimensions( texture, &width, &height ); + + // world width of decal = ptexture->width / pDecal->scale + // world height of decal = ptexture->height / pDecal->scale + // scale is inverse, scales world space to decal u/v space [0,1] + // OPTIMIZE: Get rid of these divides + decalWorldScale[0] = (float)pDecal->scale / width; + decalWorldScale[1] = (float)pDecal->scale / height; + + VectorScale( textureSpaceBasis[0], decalWorldScale[0], textureSpaceBasis[0] ); + VectorScale( textureSpaceBasis[1], decalWorldScale[1], textureSpaceBasis[1] ); +} + +// Build the initial list of vertices from the surface verts into the global array, 'verts'. +void R_SetupDecalVertsForMSurface( decal_t *pDecal, msurface_t *surf, vec3_t textureSpaceBasis[3], float *verts ) +{ + float *v; + int i; + + if( !surf->polys ) + return; + for( i = 0, v = surf->polys->verts[0]; i < surf->polys->numverts; i++, v += VERTEXSIZE, verts += VERTEXSIZE ) + { + VectorCopy( v, verts ); // copy model space coordinates + verts[3] = DotProduct( verts, textureSpaceBasis[0] ) - pDecal->dx + 0.5f; + verts[4] = DotProduct( verts, textureSpaceBasis[1] ) - pDecal->dy + 0.5f; + verts[5] = verts[6] = 0.0f; + } +} + +// Figure out where the decal maps onto the surface. +void R_SetupDecalClip( decal_t *pDecal, msurface_t *surf, int texture, vec3_t textureSpaceBasis[3], float decalWorldScale[2] ) +{ + R_SetupDecalTextureSpaceBasis( pDecal, surf, texture, textureSpaceBasis, decalWorldScale ); + + // Generate texture coordinates for each vertex in decal s,t space + // probably should pre-generate this, store it and use it for decal-decal collisions + // as in R_DecalsIntersect() + pDecal->dx = DotProduct( pDecal->position, textureSpaceBasis[0] ); + pDecal->dy = DotProduct( pDecal->position, textureSpaceBasis[1] ); +} + +// Quick and dirty sutherland Hodgman clipper +// Clip polygon to decal in texture space +// JAY: This code is lame, change it later. It does way too much work per frame +// It can be made to recursively call the clipping code and only copy the vertex list once +int R_ClipInside( float *vert, int edge ) +{ + switch( edge ) + { + case LEFT_EDGE: + if( vert[3] > 0.0f ) + return 1; + return 0; + case RIGHT_EDGE: + if( vert[3] < 1.0f ) + return 1; + return 0; + case TOP_EDGE: + if( vert[4] > 0.0f ) + return 1; + return 0; + case BOTTOM_EDGE: + if( vert[4] < 1.0f ) + return 1; + return 0; + } + return 0; +} + +void R_ClipIntersect( float *one, float *two, float *out, int edge ) +{ + float t; + + // t is the parameter of the line between one and two clipped to the edge + // or the fraction of the clipped point between one & two + // vert[0], vert[1], vert[2] is X, Y, Z + // vert[3] is u + // vert[4] is v + // vert[5] is lightmap u + // vert[6] is lightmap v + + if( edge < TOP_EDGE ) + { + if( edge == LEFT_EDGE ) + { + // left + t = ((one[3] - 0.0f) / (one[3] - two[3])); + out[3] = out[5] = 0.0f; + } + else + { + // right + t = ((one[3] - 1.0f) / (one[3] - two[3])); + out[3] = out[5] = 1.0f; + } + + out[4] = one[4] + (two[4] - one[4]) * t; + out[6] = one[6] + (two[6] - one[6]) * t; + } + else + { + if( edge == TOP_EDGE ) + { + // top + t = ((one[4] - 0.0f) / (one[4] - two[4])); + out[4] = out[6] = 0.0f; + } + else + { + // bottom + t = ((one[4] - 1.0f) / (one[4] - two[4])); + out[4] = out[6] = 1.0f; + } + + out[3] = one[3] + (two[3] - one[3]) * t; + out[5] = one[5] + (two[4] - one[5]) * t; + } + + VectorLerp( one, t, two, out ); +} + +static int SHClip( float *vert, int vertCount, float *out, int edge ) +{ + int j, outCount; + float *s, *p; + + outCount = 0; + + s = &vert[(vertCount - 1) * VERTEXSIZE]; + + for( j = 0; j < vertCount; j++ ) + { + p = &vert[j * VERTEXSIZE]; + + if( R_ClipInside( p, edge )) + { + if( R_ClipInside( s, edge )) + { + // Add a vertex and advance out to next vertex + memcpy( out, p, sizeof( float ) * VERTEXSIZE ); + out += VERTEXSIZE; + outCount++; + } + else + { + R_ClipIntersect( s, p, out, edge ); + out += VERTEXSIZE; + outCount++; + + memcpy( out, p, sizeof( float ) * VERTEXSIZE ); + out += VERTEXSIZE; + outCount++; + } + } + else + { + if( R_ClipInside( s, edge )) + { + R_ClipIntersect( p, s, out, edge ); + out += VERTEXSIZE; + outCount++; + } + } + + s = p; + } + + return outCount; +} + +float *R_DoDecalSHClip( float *pInVerts, decal_t *pDecal, int nStartVerts, int *pVertCount ) +{ + float *pOutVerts = g_DecalClipVerts[0]; + int outCount; + + // clip the polygon to the decal texture space + outCount = SHClip( pInVerts, nStartVerts, g_DecalClipVerts2[0], LEFT_EDGE ); + outCount = SHClip( g_DecalClipVerts2[0], outCount, g_DecalClipVerts[0], RIGHT_EDGE ); + outCount = SHClip( g_DecalClipVerts[0], outCount, g_DecalClipVerts2[0], TOP_EDGE ); + outCount = SHClip( g_DecalClipVerts2[0], outCount, pOutVerts, BOTTOM_EDGE ); + + if( pVertCount ) + *pVertCount = outCount; + + return pOutVerts; +} + +//----------------------------------------------------------------------------- +// Generate clipped vertex list for decal pdecal projected onto polygon psurf +//----------------------------------------------------------------------------- +float *R_DecalVertsClip( decal_t *pDecal, msurface_t *surf, int texture, int *pVertCount ) +{ + float decalWorldScale[2]; + vec3_t textureSpaceBasis[3]; + + // figure out where the decal maps onto the surface. + R_SetupDecalClip( pDecal, surf, texture, textureSpaceBasis, decalWorldScale ); + + // build the initial list of vertices from the surface verts. + R_SetupDecalVertsForMSurface( pDecal, surf, textureSpaceBasis, g_DecalClipVerts[0] ); + + if( !surf->polys ) + return 0; + return R_DoDecalSHClip( g_DecalClipVerts[0], pDecal, surf->polys->numverts, pVertCount ); +} + +// Generate lighting coordinates at each vertex for decal vertices v[] on surface psurf +static void R_DecalVertsLight( float *v, msurface_t *surf, int vertCount ) +{ + float s, t; + mtexinfo_t *tex; + mextrasurf_t *info = surf->info; + float sample_size; + int j; + + sample_size = gEngfuncs.Mod_SampleSizeForFace( surf ); + tex = surf->texinfo; + + for( j = 0; j < vertCount; j++, v += VERTEXSIZE ) + { + // lightmap texture coordinates + s = DotProduct( v, info->lmvecs[0] ) + info->lmvecs[0][3] - info->lightmapmins[0]; + s += surf->light_s * sample_size; + s += sample_size * 0.5; + s /= BLOCK_SIZE * sample_size; //fa->texinfo->texture->width; + + t = DotProduct( v, info->lmvecs[1] ) + info->lmvecs[1][3] - info->lightmapmins[1]; + t += surf->light_t * sample_size; + t += sample_size * 0.5; + t /= BLOCK_SIZE * sample_size; //fa->texinfo->texture->height; + + v[5] = s; + v[6] = t; + } +} + +// Check for intersecting decals on this surface +static decal_t *R_DecalIntersect( decalinfo_t *decalinfo, msurface_t *surf, int *pcount ) +{ + int texture; + decal_t *plast, *pDecal; + vec3_t decalExtents[2]; + float lastArea = 2; + int mapSize[2]; + + plast = NULL; + *pcount = 0; + + // (Same as R_SetupDecalClip). + texture = decalinfo->m_iTexture; + + // precalculate the extents of decalinfo's decal in world space. + R_GetDecalDimensions( texture, &mapSize[0], &mapSize[1] ); + VectorScale( decalinfo->m_Basis[0], ((mapSize[0] / decalinfo->m_scale) * 0.5f), decalExtents[0] ); + VectorScale( decalinfo->m_Basis[1], ((mapSize[1] / decalinfo->m_scale) * 0.5f), decalExtents[1] ); + + pDecal = surf->pdecals; + + while( pDecal ) + { + texture = pDecal->texture; + + // Don't steal bigger decals and replace them with smaller decals + // Don't steal permanent decals + if( !FBitSet( pDecal->flags, FDECAL_PERMANENT )) + { + vec3_t testBasis[3]; + vec3_t testPosition[2]; + float testWorldScale[2]; + vec2_t vDecalMin, vDecalMax; + vec2_t vUnionMin, vUnionMax; + + R_SetupDecalTextureSpaceBasis( pDecal, surf, texture, testBasis, testWorldScale ); + + VectorSubtract( decalinfo->m_Position, decalExtents[0], testPosition[0] ); + VectorSubtract( decalinfo->m_Position, decalExtents[1], testPosition[1] ); + + // Here, we project the min and max extents of the decal that got passed in into + // this decal's (pDecal's) [0,0,1,1] clip space, just like we would if we were + // clipping a triangle into pDecal's clip space. + Vector2Set( vDecalMin, + DotProduct( testPosition[0], testBasis[0] ) - pDecal->dx + 0.5f, + DotProduct( testPosition[1], testBasis[1] ) - pDecal->dy + 0.5f ); + + VectorAdd( decalinfo->m_Position, decalExtents[0], testPosition[0] ); + VectorAdd( decalinfo->m_Position, decalExtents[1], testPosition[1] ); + + Vector2Set( vDecalMax, + DotProduct( testPosition[0], testBasis[0] ) - pDecal->dx + 0.5f, + DotProduct( testPosition[1], testBasis[1] ) - pDecal->dy + 0.5f ); + + // Now figure out the part of the projection that intersects pDecal's + // clip box [0,0,1,1]. + Vector2Set( vUnionMin, max( vDecalMin[0], 0 ), max( vDecalMin[1], 0 )); + Vector2Set( vUnionMax, min( vDecalMax[0], 1 ), min( vDecalMax[1], 1 )); + + if( vUnionMin[0] < 1 && vUnionMin[1] < 1 && vUnionMax[0] > 0 && vUnionMax[1] > 0 ) + { + // Figure out how much of this intersects the (0,0) - (1,1) bbox. + float flArea = (vUnionMax[0] - vUnionMin[1]) * (vUnionMax[1] - vUnionMin[1]); + + if( flArea > 0.6f ) + { + *pcount += 1; + + if( !plast || flArea <= lastArea ) + { + plast = pDecal; + lastArea = flArea; + } + } + } + } + pDecal = pDecal->pnext; + } + return plast; +} + +/* +==================== +R_DecalCreatePoly + +creates mesh for decal on first rendering +==================== +*/ +glpoly_t *R_DecalCreatePoly( decalinfo_t *decalinfo, decal_t *pdecal, msurface_t *surf ) +{ + int lnumverts; + glpoly_t *poly; + float *v; + int i; + + return; + if( pdecal->polys ) // already created? + return pdecal->polys; + + v = R_DecalSetupVerts( pdecal, surf, pdecal->texture, &lnumverts ); + if( !lnumverts ) return NULL; // probably this never happens + + // allocate glpoly + // REFTODO: com_studiocache pool! + poly = Mem_Calloc( r_temppool, sizeof( glpoly_t ) + ( lnumverts - 4 ) * VERTEXSIZE * sizeof( float )); + poly->next = pdecal->polys; + poly->flags = surf->flags; + pdecal->polys = poly; + poly->numverts = lnumverts; + + for( i = 0; i < lnumverts; i++, v += VERTEXSIZE ) + { + VectorCopy( v, poly->verts[i] ); + poly->verts[i][3] = v[3]; + poly->verts[i][4] = v[4]; + poly->verts[i][5] = v[5]; + poly->verts[i][6] = v[6]; + } + + return poly; +} + +// Add the decal to the surface's list of decals. +static void R_AddDecalToSurface( decal_t *pdecal, msurface_t *surf, decalinfo_t *decalinfo ) +{ + decal_t *pold; + + pdecal->pnext = NULL; + pold = surf->pdecals; + + if( pold ) + { + while( pold->pnext ) + pold = pold->pnext; + pold->pnext = pdecal; + } + else + { + surf->pdecals = pdecal; + } + + // force surface cache rebuild + surf->dlightframe = r_framecount + 1; + + // tag surface + pdecal->psurface = surf; + + // at this point decal are linked with surface + // and will be culled, drawing and sorting + // together with surface + + // alloc clipped poly for decal + R_DecalCreatePoly( decalinfo, pdecal, surf ); + //R_AddDecalVBO( pdecal, surf ); +} + +static void R_DecalCreate( decalinfo_t *decalinfo, msurface_t *surf, float x, float y ) +{ + decal_t *pdecal, *pold; + int count, vertCount; + + if( !surf ) return; // ??? + + pold = R_DecalIntersect( decalinfo, surf, &count ); + if( count < MAX_OVERLAP_DECALS ) pold = NULL; + + pdecal = R_DecalAlloc( pold ); + if( !pdecal ) return; // r_decals == 0 ??? + + pdecal->flags = decalinfo->m_Flags; + + VectorCopy( decalinfo->m_Position, pdecal->position ); + + pdecal->dx = x; + pdecal->dy = y; + + // set scaling + pdecal->scale = decalinfo->m_scale; + pdecal->entityIndex = decalinfo->m_Entity; + pdecal->texture = decalinfo->m_iTexture; + + // check to see if the decal actually intersects the surface + // if not, then remove the decal + R_DecalVertsClip( pdecal, surf, decalinfo->m_iTexture, &vertCount ); + + if( !vertCount ) + { + R_DecalUnlink( pdecal ); + return; + } + + // add to the surface's list + R_AddDecalToSurface( pdecal, surf, decalinfo ); +} + +void R_DecalSurface( msurface_t *surf, decalinfo_t *decalinfo ) +{ + // get the texture associated with this surface + mtexinfo_t *tex = surf->texinfo; + decal_t *decal = surf->pdecals; + vec4_t textureU, textureV; + float s, t, w, h; + connstate_t state = ENGINE_GET_PARM( PARM_CONNSTATE ); + + // we in restore mode + if( state == ca_connected || state == ca_validate ) + { + // NOTE: we may have the decal on this surface that come from another level. + // check duplicate with same position and texture + while( decal != NULL ) + { + if( VectorCompare( decal->position, decalinfo->m_Position ) && decal->texture == decalinfo->m_iTexture ) + return; // decal already exists, don't place it again + decal = decal->pnext; + } + } + + Vector4Copy( tex->vecs[0], textureU ); + Vector4Copy( tex->vecs[1], textureV ); + + // project decal center into the texture space of the surface + s = DotProduct( decalinfo->m_Position, textureU ) + textureU[3] - surf->texturemins[0]; + t = DotProduct( decalinfo->m_Position, textureV ) + textureV[3] - surf->texturemins[1]; + + // Determine the decal basis (measured in world space) + // Note that the decal basis vectors 0 and 1 will always lie in the same + // plane as the texture space basis vectorstextureVecsTexelsPerWorldUnits. + R_DecalComputeBasis( surf, decalinfo->m_Flags, decalinfo->m_Basis ); + + // Compute an effective width and height (axis aligned) in the parent texture space + // How does this work? decalBasis[0] represents the u-direction (width) + // of the decal measured in world space, decalBasis[1] represents the + // v-direction (height) measured in world space. + // textureVecsTexelsPerWorldUnits[0] represents the u direction of + // the surface's texture space measured in world space (with the appropriate + // scale factor folded in), and textureVecsTexelsPerWorldUnits[1] + // represents the texture space v direction. We want to find the dimensions (w,h) + // of a square measured in texture space, axis aligned to that coordinate system. + // All we need to do is to find the components of the decal edge vectors + // (decalWidth * decalBasis[0], decalHeight * decalBasis[1]) + // in texture coordinates: + + w = fabs( decalinfo->m_decalWidth * DotProduct( textureU, decalinfo->m_Basis[0] )) + + fabs( decalinfo->m_decalHeight * DotProduct( textureU, decalinfo->m_Basis[1] )); + + h = fabs( decalinfo->m_decalWidth * DotProduct( textureV, decalinfo->m_Basis[0] )) + + fabs( decalinfo->m_decalHeight * DotProduct( textureV, decalinfo->m_Basis[1] )); + + // move s,t to upper left corner + s -= ( w * 0.5f ); + t -= ( h * 0.5f ); + + // Is this rect within the surface? -- tex width & height are unsigned + if( s <= -w || t <= -h || s > (surf->extents[0] + w) || t > (surf->extents[1] + h)) + { + return; // nope + } + + // stamp it + R_DecalCreate( decalinfo, surf, s, t ); +} + +//----------------------------------------------------------------------------- +// iterate over all surfaces on a node, looking for surfaces to decal +//----------------------------------------------------------------------------- +static void R_DecalNodeSurfaces( model_t *model, mnode_t *node, decalinfo_t *decalinfo ) +{ + // iterate over all surfaces in the node + msurface_t *surf; + int i; + + surf = model->surfaces + node->firstsurface; + + for( i = 0; i < node->numsurfaces; i++, surf++ ) + { + // never apply decals on the water or sky surfaces + if( surf->flags & (SURF_DRAWTURB|SURF_DRAWSKY|SURF_CONVEYOR)) + continue; + + // we can implement alpha testing without stencil + //if( surf->flags & SURF_TRANSPARENT && !glState.stencilEnabled ) + //continue; + + R_DecalSurface( surf, decalinfo ); + } +} + +//----------------------------------------------------------------------------- +// Recursive routine to find surface to apply a decal to. World coordinates of +// the decal are passed in r_recalpos like the rest of the engine. This should +// be called through R_DecalShoot() +//----------------------------------------------------------------------------- +static void R_DecalNode( model_t *model, mnode_t *node, decalinfo_t *decalinfo ) +{ + mplane_t *splitplane; + float dist; + + Assert( node != NULL ); + + if( node->contents < 0 ) + { + // hit a leaf + return; + } + + splitplane = node->plane; + dist = DotProduct( decalinfo->m_Position, splitplane->normal ) - splitplane->dist; + + // This is arbitrarily set to 10 right now. In an ideal world we'd have the + // exact surface but we don't so, this tells me which planes are "sort of + // close" to the gunshot -- the gunshot is actually 4 units in front of the + // wall (see dlls\weapons.cpp). We also need to check to see if the decal + // actually intersects the texture space of the surface, as this method tags + // parallel surfaces in the same node always. + // JAY: This still tags faces that aren't correct at edges because we don't + // have a surface normal + if( dist > decalinfo->m_Size ) + { + R_DecalNode( model, node->children[0], decalinfo ); + } + else if( dist < -decalinfo->m_Size ) + { + R_DecalNode( model, node->children[1], decalinfo ); + } + else + { + if( dist < DECAL_DISTANCE && dist > -DECAL_DISTANCE ) + R_DecalNodeSurfaces( model, node, decalinfo ); + + R_DecalNode( model, node->children[0], decalinfo ); + R_DecalNode( model, node->children[1], decalinfo ); + } +} + +// Shoots a decal onto the surface of the BSP. position is the center of the decal in world coords +void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale ) +{ + decalinfo_t decalInfo; + cl_entity_t *ent = NULL; + model_t *model = NULL; + int width, height; + hull_t *hull; + + if( textureIndex <= 0 || textureIndex >= MAX_TEXTURES ) + { + gEngfuncs.Con_Printf( S_ERROR "Decal has invalid texture!\n" ); + return; + } + + if( entityIndex > 0 ) + { + ent = gEngfuncs.GetEntityByIndex( entityIndex ); + + if( modelIndex > 0 ) model = gEngfuncs.pfnGetModelByIndex( modelIndex ); + else if( ent != NULL ) model = gEngfuncs.pfnGetModelByIndex( ent->curstate.modelindex ); + else return; + } + else if( modelIndex > 0 ) + model = gEngfuncs.pfnGetModelByIndex( modelIndex ); + else model = WORLDMODEL; + + if( !model ) return; + + if( model->type != mod_brush ) + { + gEngfuncs.Con_Printf( S_ERROR "Decals must hit mod_brush!\n" ); + return; + } + + decalInfo.m_pModel = model; + hull = &model->hulls[0]; // always use #0 hull + + // NOTE: all the decals at 'first shoot' placed into local space of parent entity + // and won't transform again on a next restore, levelchange etc + if( ent && !FBitSet( flags, FDECAL_LOCAL_SPACE )) + { + vec3_t pos_l; + + // transform decal position in local bmodel space + if( !VectorIsNull( ent->angles )) + { + matrix4x4 matrix; + + Matrix4x4_CreateFromEntity( matrix, ent->angles, ent->origin, 1.0f ); + Matrix4x4_VectorITransform( matrix, pos, pos_l ); + } + else + { + VectorSubtract( pos, ent->origin, pos_l ); + } + + VectorCopy( pos_l, decalInfo.m_Position ); + // decal position moved into local space + SetBits( flags, FDECAL_LOCAL_SPACE ); + } + else + { + // already in local space + VectorCopy( pos, decalInfo.m_Position ); + } + + // this decal must use landmark for correct transition + // because their model exist only in world-space + if( !FBitSet( model->flags, MODEL_HAS_ORIGIN )) + SetBits( flags, FDECAL_USE_LANDMARK ); + + // more state used by R_DecalNode() + decalInfo.m_iTexture = textureIndex; + decalInfo.m_Entity = entityIndex; + decalInfo.m_Flags = flags; + + R_GetDecalDimensions( textureIndex, &width, &height ); + decalInfo.m_Size = width >> 1; + if(( height >> 1 ) > decalInfo.m_Size ) + decalInfo.m_Size = height >> 1; + + decalInfo.m_scale = bound( MIN_DECAL_SCALE, scale, MAX_DECAL_SCALE ); + + // compute the decal dimensions in world space + decalInfo.m_decalWidth = width / decalInfo.m_scale; + decalInfo.m_decalHeight = height / decalInfo.m_scale; + + R_DecalNode( model, &model->nodes[hull->firstclipnode], &decalInfo ); +} + +// Build the vertex list for a decal on a surface and clip it to the surface. +// This is a template so it can work on world surfaces and dynamic displacement +// triangles the same way. +float *R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, int texture, int *outCount ) +{ + glpoly_t *p = pDecal->polys; + int i, count; + float *v, *v2; + + if( p ) + { + v = g_DecalClipVerts[0]; + count = p->numverts; + v2 = p->verts[0]; + + // if we have mesh so skip clipping and just copy vertexes out (perf) + for( i = 0; i < count; i++, v += VERTEXSIZE, v2 += VERTEXSIZE ) + { + VectorCopy( v2, v ); + v[3] = v2[3]; + v[4] = v2[4]; + v[5] = v2[5]; + v[6] = v2[6]; + } + + // restore pointer + v = g_DecalClipVerts[0]; + } + else + { + v = R_DecalVertsClip( pDecal, surf, texture, &count ); + R_DecalVertsLight( v, surf, count ); + } + + if( outCount ) + *outCount = count; + + return v; +} + +#if 0 +void DrawSingleDecal( decal_t *pDecal, msurface_t *fa ) +{ + float *v; + int i, numVerts; + + v = R_DecalSetupVerts( pDecal, fa, pDecal->texture, &numVerts ); + if( !numVerts ) return; + + GL_Bind( XASH_TEXTURE0, pDecal->texture ); + + pglBegin( GL_POLYGON ); + + for( i = 0; i < numVerts; i++, v += VERTEXSIZE ) + { + pglTexCoord2f( v[3], v[4] ); + pglVertex3fv( v ); + } + + pglEnd(); +} + +void DrawSurfaceDecals( msurface_t *fa, qboolean single, qboolean reverse ) +{ + decal_t *p; + cl_entity_t *e; + + if( !fa->pdecals ) return; + + e = RI.currententity; + Assert( e != NULL ); + + if( single ) + { + if( e->curstate.rendermode == kRenderNormal || e->curstate.rendermode == kRenderTransAlpha ) + { + pglDepthMask( GL_FALSE ); + pglEnable( GL_BLEND ); + + if( e->curstate.rendermode == kRenderTransAlpha ) + pglDisable( GL_ALPHA_TEST ); + } + + if( e->curstate.rendermode == kRenderTransColor ) + pglEnable( GL_TEXTURE_2D ); + + if( e->curstate.rendermode == kRenderTransTexture || e->curstate.rendermode == kRenderTransAdd ) + GL_Cull( GL_NONE ); + + if( gl_polyoffset->value ) + { + pglEnable( GL_POLYGON_OFFSET_FILL ); + pglPolygonOffset( -1.0f, -gl_polyoffset->value ); + } + } + + if( FBitSet( fa->flags, SURF_TRANSPARENT ) && glState.stencilEnabled ) + { + mtexinfo_t *tex = fa->texinfo; + + for( p = fa->pdecals; p; p = p->pnext ) + { + if( p->texture ) + { + float *o, *v; + int i, numVerts; + o = R_DecalSetupVerts( p, fa, p->texture, &numVerts ); + + pglEnable( GL_STENCIL_TEST ); + pglStencilFunc( GL_ALWAYS, 1, 0xFFFFFFFF ); + pglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); + + pglStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE ); + pglBegin( GL_POLYGON ); + + for( i = 0, v = o; i < numVerts; i++, v += VERTEXSIZE ) + { + v[5] = ( DotProduct( v, tex->vecs[0] ) + tex->vecs[0][3] ) / tex->texture->width; + v[6] = ( DotProduct( v, tex->vecs[1] ) + tex->vecs[1][3] ) / tex->texture->height; + + pglTexCoord2f( v[5], v[6] ); + pglVertex3fv( v ); + } + + pglEnd(); + pglStencilOp( GL_KEEP, GL_KEEP, GL_DECR ); + + pglEnable( GL_ALPHA_TEST ); + pglBegin( GL_POLYGON ); + + for( i = 0, v = o; i < numVerts; i++, v += VERTEXSIZE ) + { + pglTexCoord2f( v[5], v[6] ); + pglVertex3fv( v ); + } + + pglEnd(); + pglDisable( GL_ALPHA_TEST ); + + pglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); + pglStencilFunc( GL_EQUAL, 0, 0xFFFFFFFF ); + pglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); + } + } + } + + pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + + if( reverse && e->curstate.rendermode == kRenderTransTexture ) + { + decal_t *list[1024]; + int i, count; + + for( p = fa->pdecals, count = 0; p && count < 1024; p = p->pnext ) + if( p->texture ) list[count++] = p; + + for( i = count - 1; i >= 0; i-- ) + DrawSingleDecal( list[i], fa ); + } + else + { + for( p = fa->pdecals; p; p = p->pnext ) + { + if( !p->texture ) continue; + DrawSingleDecal( p, fa ); + } + } + + if( FBitSet( fa->flags, SURF_TRANSPARENT ) && glState.stencilEnabled ) + pglDisable( GL_STENCIL_TEST ); + + if( single ) + { + if( e->curstate.rendermode == kRenderNormal || e->curstate.rendermode == kRenderTransAlpha ) + { + pglDepthMask( GL_TRUE ); + pglDisable( GL_BLEND ); + + if( e->curstate.rendermode == kRenderTransAlpha ) + pglEnable( GL_ALPHA_TEST ); + } + + if( gl_polyoffset->value ) + pglDisable( GL_POLYGON_OFFSET_FILL ); + + if( e->curstate.rendermode == kRenderTransTexture || e->curstate.rendermode == kRenderTransAdd ) + GL_Cull( GL_FRONT ); + + if( e->curstate.rendermode == kRenderTransColor ) + pglDisable( GL_TEXTURE_2D ); + + // restore blendfunc here + if( e->curstate.rendermode == kRenderTransAdd || e->curstate.rendermode == kRenderGlow ) + pglBlendFunc( GL_SRC_ALPHA, GL_ONE ); + + pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + } +} + +void DrawDecalsBatch( void ) +{ + cl_entity_t *e; + int i; + + if( !tr.num_draw_decals ) + return; + + e = RI.currententity; + Assert( e != NULL ); + + if( e->curstate.rendermode != kRenderTransTexture ) + { + pglEnable( GL_BLEND ); + pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + pglDepthMask( GL_FALSE ); + } + + if( e->curstate.rendermode == kRenderTransTexture || e->curstate.rendermode == kRenderTransAdd ) + GL_Cull( GL_NONE ); + + if( gl_polyoffset->value ) + { + pglEnable( GL_POLYGON_OFFSET_FILL ); + pglPolygonOffset( -1.0f, -gl_polyoffset->value ); + } + + for( i = 0; i < tr.num_draw_decals; i++ ) + { + DrawSurfaceDecals( tr.draw_decals[i], false, false ); + } + + if( e->curstate.rendermode != kRenderTransTexture ) + { + pglDepthMask( GL_TRUE ); + pglDisable( GL_BLEND ); + pglDisable( GL_ALPHA_TEST ); + } + + if( gl_polyoffset->value ) + pglDisable( GL_POLYGON_OFFSET_FILL ); + + if( e->curstate.rendermode == kRenderTransTexture || e->curstate.rendermode == kRenderTransAdd ) + GL_Cull( GL_FRONT ); + + tr.num_draw_decals = 0; +} +#endif +/* +============================================================= + + DECALS SERIALIZATION + +============================================================= +*/ +static qboolean R_DecalUnProject( decal_t *pdecal, decallist_t *entry ) +{ + if( !pdecal || !( pdecal->psurface )) + return false; + + VectorCopy( pdecal->position, entry->position ); + entry->entityIndex = pdecal->entityIndex; + + // Grab surface plane equation + if( pdecal->psurface->flags & SURF_PLANEBACK ) + VectorNegate( pdecal->psurface->plane->normal, entry->impactPlaneNormal ); + else VectorCopy( pdecal->psurface->plane->normal, entry->impactPlaneNormal ); + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pList - +// count - +// Output : static int +//----------------------------------------------------------------------------- +static int DecalListAdd( decallist_t *pList, int count ) +{ + vec3_t tmp; + decallist_t *pdecal; + int i; + + pdecal = pList + count; + + for( i = 0; i < count; i++ ) + { + if( !Q_strcmp( pdecal->name, pList[i].name ) && pdecal->entityIndex == pList[i].entityIndex ) + { + VectorSubtract( pdecal->position, pList[i].position, tmp ); // Merge + + if( VectorLength( tmp ) < DECAL_OVERLAP_DISTANCE ) + return count; + } + } + + // this is a new decal + return count + 1; +} + +static int DecalDepthCompare( const void *a, const void *b ) +{ + const decallist_t *elem1, *elem2; + + elem1 = (const decallist_t *)a; + elem2 = (const decallist_t *)b; + + if( elem1->depth > elem2->depth ) + return 1; + if( elem1->depth < elem2->depth ) + return -1; + + return 0; +} + +//----------------------------------------------------------------------------- +// Purpose: Called by CSaveRestore::SaveClientState +// Input : *pList - +// Output : int +//----------------------------------------------------------------------------- +int R_CreateDecalList( decallist_t *pList ) +{ + int total = 0; + int i, depth; + + if( WORLDMODEL ) + { + for( i = 0; i < MAX_RENDER_DECALS; i++ ) + { + decal_t *decal = &gDecalPool[i]; + decal_t *pdecals; + + // decal is in use and is not a custom decal + if( decal->psurface == NULL || FBitSet( decal->flags, FDECAL_DONTSAVE )) + continue; + + // compute depth + depth = 0; + pdecals = decal->psurface->pdecals; + + while( pdecals && pdecals != decal ) + { + depth++; + pdecals = pdecals->pnext; + } + + pList[total].depth = depth; + pList[total].flags = decal->flags; + pList[total].scale = decal->scale; + + R_DecalUnProject( decal, &pList[total] ); + COM_FileBase( R_GetTexture( decal->texture )->name, pList[total].name ); + + // check to see if the decal should be added + total = DecalListAdd( pList, total ); + } + + if( gEngfuncs.drawFuncs->R_CreateStudioDecalList ) + { + total += gEngfuncs.drawFuncs->R_CreateStudioDecalList( pList, total ); + } + } + + // sort the decals lowest depth first, so they can be re-applied in order + qsort( pList, total, sizeof( decallist_t ), DecalDepthCompare ); + + return total; +} + +/* +=============== +R_DecalRemoveAll + +remove all decals with specified texture +=============== +*/ +void R_DecalRemoveAll( int textureIndex ) +{ + decal_t *pdecal; + int i; + + if( textureIndex < 0 || textureIndex >= MAX_TEXTURES ) + return; // out of bounds + + for( i = 0; i < gDecalCount; i++ ) + { + pdecal = &gDecalPool[i]; + + // don't remove permanent decals + if( !textureIndex && FBitSet( pdecal->flags, FDECAL_PERMANENT )) + continue; + + if( !textureIndex || ( pdecal->texture == textureIndex )) + R_DecalUnlink( pdecal ); + } +} + +/* +=============== +R_EntityRemoveDecals + +remove all decals from specified entity +=============== +*/ +void R_EntityRemoveDecals( model_t *mod ) +{ + msurface_t *psurf; + decal_t *p; + int i; + + if( !mod || mod->type != mod_brush ) + return; + + psurf = &mod->surfaces[mod->firstmodelsurface]; + for( i = 0; i < mod->nummodelsurfaces; i++, psurf++ ) + { + for( p = psurf->pdecals; p; p = p->pnext ) + R_DecalUnlink( p ); + } +} + +/* +=============== +R_ClearAllDecals + +remove all decals from anything +used for full decals restart +=============== +*/ +void R_ClearAllDecals( void ) +{ + decal_t *pdecal; + int i; + + // because gDecalCount may be zeroed after recach the decal limit + for( i = 0; i < MAX_RENDER_DECALS; i++ ) + { + pdecal = &gDecalPool[i]; + R_DecalUnlink( pdecal ); + } + + if( gEngfuncs.drawFuncs->R_ClearStudioDecals ) + { + gEngfuncs.drawFuncs->R_ClearStudioDecals(); + } +} diff --git a/r_local.h b/r_local.h index 56c74af5..5ed57284 100644 --- a/r_local.h +++ b/r_local.h @@ -406,18 +406,18 @@ int R_CullModel( cl_entity_t *e, const vec3_t absmin, const vec3_t absmax ); qboolean R_CullBox( const vec3_t mins, const vec3_t maxs ); qboolean R_CullSphere( const vec3_t centre, const float radius ); //int R_CullSurface( msurface_t *surf, gl_frustum_t *frustum, uint clipflags ); - +#endif // // gl_decals.c // void DrawSurfaceDecals( msurface_t *fa, qboolean single, qboolean reverse ); float *R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, int texture, int *outCount ); -void DrawSingleDecal( decal_t *pDecal, msurface_t *fa ); +//void DrawSingleDecal( decal_t *pDecal, msurface_t *fa ); void R_EntityRemoveDecals( model_t *mod ); -void DrawDecalsBatch( void ); +//void DrawDecalsBatch( void ); void R_ClearDecals( void ); - +#if 0 // // gl_drawhulls.c @@ -1223,6 +1223,8 @@ extern cvar_t *sw_stipplealpha; extern cvar_t *sw_surfcacheoverride; extern cvar_t *sw_waterwarp; extern cvar_t *sw_texfilt; +extern cvar_t *r_decals; + extern vec3_t modelorg; extern vec3_t r_origin; diff --git a/r_main.c b/r_main.c index d58186c2..08249aab 100644 --- a/r_main.c +++ b/r_main.c @@ -104,6 +104,8 @@ cvar_t *vid_gamma; cvar_t *sw_lockpvs; //PGM +cvar_t *r_decals; + mleaf_t *r_viewleaf; int r_viewcluster, r_oldviewcluster; @@ -1925,7 +1927,7 @@ qboolean R_Init() sw_texfilt = gEngfuncs.Cvar_Get ("sw_texfilt", "0", 0, "texture dither"); //r_lefthand = ri.Cvar_Get( "hand", "0", FCVAR_USERINFO | FCVAR_ARCHIVE ); // r_speeds = ri.Cvar_Get ("r_speeds", "0", 0); - + r_decals = gEngfuncs.pfnGetCvarPointer( "r_decals", 0 ); //r_drawworld = ri.Cvar_Get ("r_drawworld", "1", 0); //r_dspeeds = ri.Cvar_Get ("r_dspeeds", "0", 0); // r_lightlevel = ri.Cvar_Get ("r_lightlevel", "0", 0); diff --git a/r_surf.c b/r_surf.c index 784ca161..3d7fc918 100644 --- a/r_surf.c +++ b/r_surf.c @@ -147,9 +147,9 @@ void R_AddDynamicLights( msurface_t *surf ) if( dist < minlight ) { - printf("dlight %f\n", dist); + //printf("dlight %f\n", dist); //*(void**)0 = 0; - bl[0] += ((int)((rad - dist) * 256) * 7.5) / 256; + bl[0] += ((int)((rad - dist) * 256) * 7.5); //bl[1] += ((int)((rad - dist) * 256) * 2.5) / 256; //bl[2] += ((int)((rad - dist) * 256) * 2.5) / 256; } @@ -237,7 +237,7 @@ static void R_BuildLightMap( ) t = 0; if( t > 65535 * 3 ) t = 65535 * 3; - t = t * 31 / 65535 / 3;//(255*256 - t) >> (8 - VID_CBITS); + t = t / 2048 / 3;//(255*256 - t) >> (8 - VID_CBITS); //if (t < (1 << 6)) //t = (1 << 6); @@ -961,6 +961,127 @@ int D_log2 (int num) } //============================================================================= +void R_DecalComputeBasis( msurface_t *surf, int flags, vec3_t textureSpaceBasis[3] ); +void R_DrawSurfaceDecals() +{ + msurface_t *fa = r_drawsurf.surf; + decal_t *p; + + for( p = fa->pdecals; p; p = p->pnext) + { + pixel_t *dest, *source; + vec4_t textureU, textureV; + image_t *tex = R_GetTexture( p->texture ); + int s1 = 0,t1 = 0, s2 = tex->width, t2 = tex->height; + unsigned int height; + unsigned int f, fstep; + int skip; + pixel_t *buffer; + qboolean transparent; + int x, y, u,v, sv, w, h; + vec3_t basis[3]; + + Vector4Copy( fa->texinfo->vecs[0], textureU ); + Vector4Copy( fa->texinfo->vecs[1], textureV ); + + R_DecalComputeBasis( fa, 0, basis ); + + w = fabs( tex->width * DotProduct( textureU, basis[0] )) + + fabs( tex->height * DotProduct( textureU, basis[1] )); + h = fabs( tex->width * DotProduct( textureV, basis[0] )) + + fabs( tex->height * DotProduct( textureV, basis[1] )); + + // project decal center into the texture space of the surface + x = DotProduct( p->position, textureU ) + textureU[3] - fa->texturemins[0] - w/2; + y = DotProduct( p->position, textureV ) + textureV[3] - fa->texturemins[1] - h/2; + + x = x >> r_drawsurf.surfmip; + y = y >> r_drawsurf.surfmip; + w = w >> r_drawsurf.surfmip; + h = h >> r_drawsurf.surfmip; + + if( x < 0 ) + { + s1 += (-x)*(s2-s1) / w; + x = 0; + } + if( x + w > r_drawsurf.surfwidth ) + { + s2 -= (x + w - r_drawsurf.surfwidth) * (s2 - s1)/ w ; + w = r_drawsurf.surfwidth - x; + } + if( y + h > r_drawsurf.surfheight ) + { + t2 -= (y + h - r_drawsurf.surfheight) * (t2 - t1) / h; + h = r_drawsurf.surfheight - y; + } + + if( !tex->pixels[0] || s1 >= s2 || t1 >= t2 ) + continue; + + if( tex->alpha_pixels ) + { + buffer = tex->alpha_pixels; + transparent = true; + } + else + buffer = tex->pixels[0]; + + height = h; + if (y < 0) + { + skip = -y; + height += y; + y = 0; + } + else + skip = 0; + + dest = ((pixel_t*)r_drawsurf.surfdat) + y * r_drawsurf.rowbytes + x; + + for (v=0 ; vwidth + s1; + + { + f = 0; + fstep = s2*0x10000/w; + if( w == s2 - s1 ) + fstep = 0x10000; + + for (u=0 ; u>16]; + int alpha = 7; + f += fstep; + + if( transparent ) + { + alpha &= src >> 16 - 3; + src = src << 3; + } + + if( alpha <= 0 ) + continue; + + if( alpha < 7) // && (vid.rendermode == kRenderTransAlpha || vid.rendermode == kRenderTransTexture ) ) + { + pixel_t screen = dest[u]; // | 0xff & screen & src ; + dest[u] = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 3); + + } + else + dest[u] = src; + + } + } + dest += r_drawsurf.rowbytes; + } + } + +} /* ================ @@ -1054,6 +1175,7 @@ surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) // rasterize the surface into the cache R_DrawSurface (); + R_DrawSurfaceDecals(); return cache; } From 7f8caf163429abf7c7537edb2c087cf9aea7ad04 Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 28 Mar 2019 02:33:49 +0700 Subject: [PATCH 036/115] ref_soft: Fix crash on glowshell, tune decals blending --- r_polyse.c | 2 +- r_studio.c | 6 ++++++ r_surf.c | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/r_polyse.c b/r_polyse.c index 0852d2c5..c8de02fd 100644 --- a/r_polyse.c +++ b/r_polyse.c @@ -1192,7 +1192,7 @@ void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) *lpdest = ((byte *)vid.colormap)[irtable[*lptex]]; else*/ //*lpdest = *lptex; //((byte *)vid.colormap)[*lptex + (llight & 0xFF00)]; - uint src = *lptex; + pixel_t src = *lptex; //*lpdest = //vid.colormap[src & 0xff00|(llight>>8)] << 8 | (src & llight & 0xff) | ((src & 0xff) >> 3); // very dirty, maybe need dual colormap? //*lpdest = (vid.colormap[src >> 8 | (llight & 0xFF00)] << 8) | src & 0xff; diff --git a/r_studio.c b/r_studio.c index 48b2e623..4b99f998 100644 --- a/r_studio.c +++ b/r_studio.c @@ -1817,7 +1817,13 @@ static void R_StudioSetupSkin( studiohdr_t *ptexturehdr, int index ) image_t *image; if( FBitSet( g_nForceFaceFlags, STUDIO_NF_CHROME )) + { + image = R_GetTexture(tr.whiteTexture); + r_affinetridesc.pskin = image->pixels[0]; + r_affinetridesc.skinwidth = image->width; + r_affinetridesc.skinheight = image->height; return; + } if( ptexturehdr == NULL ) return; diff --git a/r_surf.c b/r_surf.c index 3d7fc918..cd032d3b 100644 --- a/r_surf.c +++ b/r_surf.c @@ -1069,7 +1069,7 @@ void R_DrawSurfaceDecals() if( alpha < 7) // && (vid.rendermode == kRenderTransAlpha || vid.rendermode == kRenderTransTexture ) ) { pixel_t screen = dest[u]; // | 0xff & screen & src ; - dest[u] = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 3); + dest[u] = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0x7f) >> 3 | ((src & 0xff)); } else From 72d5dfed340ce1c636d429561731e6b3a41dbc44 Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 28 Mar 2019 03:42:28 +0700 Subject: [PATCH 037/115] ref_soft: Fill sky, enable turb code (not working correctly) --- r_edge.c | 13 +++++++++---- r_main.c | 2 +- r_rast.c | 4 ++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/r_edge.c b/r_edge.c index e6251b03..59443524 100644 --- a/r_edge.c +++ b/r_edge.c @@ -920,10 +920,10 @@ void D_TurbulentSurf (surf_t *s) //============ //PGM // textures that aren't warping are just flowing. Use NonTurbulent8 instead -#if 1 - NonTurbulent8 (s->spans); +#if 0 + Turbulent8 (s->spans); #else - if(!(pface->texinfo->flags & SURF_DRAWTURB)) + if(!(pface->flags & SURF_DRAWTURB)) NonTurbulent8 (s->spans); else Turbulent8 (s->spans); @@ -1123,7 +1123,12 @@ void D_DrawSurfaces (void) r_drawnpolycount++; #if 1 - D_SolidSurf (s); + if(s->flags & SURF_DRAWSKY) + D_BackgroundSurf (s); + else if (s->flags & SURF_DRAWTURB) + D_TurbulentSurf (s); + else + D_SolidSurf (s); #else if (! (s->flags & (SURF_DRAWSKYBOX|SURF_DRAWBACKGROUND|SURF_DRAWTURB) ) ) D_SolidSurf (s); diff --git a/r_main.c b/r_main.c index 08249aab..8bd9e029 100644 --- a/r_main.c +++ b/r_main.c @@ -1912,7 +1912,7 @@ qboolean R_Init() // sw_aliasstats = ri.Cvar_Get ("sw_polymodelstats", "0", 0); // sw_allow_modex = ri.Cvar_Get( "sw_allow_modex", "1", CVAR_ARCHIVE ); - sw_clearcolor = gEngfuncs.Cvar_Get ("sw_clearcolor", "2", 0, "screen clear color"); + sw_clearcolor = gEngfuncs.Cvar_Get ("sw_clearcolor", "48999", 0, "screen clear color"); sw_drawflat = gEngfuncs.Cvar_Get ("sw_drawflat", "0", 0, ""); sw_draworder = gEngfuncs.Cvar_Get ("sw_draworder", "0", 0, ""); sw_maxedges = gEngfuncs.Cvar_Get ("sw_maxedges", "32", 0, ""); diff --git a/r_rast.c b/r_rast.c index 9b6b2b25..fee7619c 100644 --- a/r_rast.c +++ b/r_rast.c @@ -544,7 +544,7 @@ void R_RenderFace (msurface_t *fa, int clipflags) { //fa->nextalphasurface = r_alpha_surfaces; //r_alpha_surfaces = fa; - return; + //return; } // sky surfaces encountered in the world will cause the @@ -552,7 +552,7 @@ void R_RenderFace (msurface_t *fa, int clipflags) if ( fa->flags & SURF_DRAWSKY ) { //R_EmitSkyBox (); - return; + // return; } // skip out if no more surfs From 77e296ffef327d5ee45d0c6460597a87018b457d Mon Sep 17 00:00:00 2001 From: mittorn Date: Fri, 29 Mar 2019 02:02:38 +0700 Subject: [PATCH 038/115] ref_soft: Add r_poly, transparent brushes support --- r_bsp.c | 99 ++++ r_image.c | 3 +- r_local.h | 18 +- r_main.c | 33 +- r_poly.c | 1275 ++++++++++++++++++++++++++++++++++++++++++++++++++ r_surf.c | 4 + r_trialias.c | 72 +++ 7 files changed, 1489 insertions(+), 15 deletions(-) create mode 100644 r_poly.c diff --git a/r_bsp.c b/r_bsp.c index 3478e1cf..cdb8d6db 100644 --- a/r_bsp.c +++ b/r_bsp.c @@ -920,3 +920,102 @@ void R_RenderWorld (void) } + +/* +================ +R_DrawBrushModel + +not covered by edge drawing +================ +*/ +void R_DrawBrushModel(cl_entity_t *pent) +{ + int i; + vec_t dot; + msurface_t *psurf; + int numsurfaces; + mplane_t *pplane; + vec3_t mins, maxs; + float minmaxs[6]; + int clipflags, k; + model_t *pmodel; + vec3_t oldorigin; + VectorCopy (modelorg, oldorigin); + insubmodel = true; + if( !pent || !pent->model ) + return; + + pmodel = pent->model; + + if (pmodel->type != mod_brush) + return; + + if (pmodel->nummodelsurfaces == 0) + return; // clip brush only +#if 0 +// FIXME: use bounding-box-based frustum clipping info? + RotatedBBox (pmodel->mins, pmodel->maxs, + RI.currententity->angles, mins, maxs); + + VectorAdd (mins, RI.currententity->origin, minmaxs); + VectorAdd (maxs, RI.currententity->origin, (minmaxs+3)); + + clipflags = R_BmodelCheckBBox (minmaxs); + if (clipflags == BMODEL_FULLY_CLIPPED) + return; // off the edge of the screen + + R_RotateBmodel (); + + VectorCopy (RI.currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + //VectorSubtract (r_origin, RI.currententity->origin, modelorg); + r_pcurrentvertbase = pmodel->vertexes; + + // calculate dynamic lighting for bmodel + for( k = 0; k < MAX_DLIGHTS; k++ ) + { + dlight_t *l = gEngfuncs.GetDynamicLight( k ); + + if( l->die < gpGlobals->time || !l->radius ) + continue; + + /*VectorCopy( l->origin, oldorigin ); // save lightorigin + Matrix4x4_VectorITransform( RI.objectMatrix, l->origin, origin_l ); + VectorCopy( origin_l, l->origin ); // move light in bmodel space + R_MarkLights( l, 1<nodes + clmodel->hulls[0].firstclipnode ); + VectorCopy( oldorigin, l->origin ); // restore lightorigin*/ + R_MarkLights( l, 1<nodes + pmodel->hulls[0].firstclipnode ); + } +#endif + psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; + numsurfaces = pmodel->nummodelsurfaces; + + for (i=0 ; iplane; + + dot = DotProduct (modelorg, pplane->normal) - pplane->dist; + + // draw the polygon + if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || + (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) + { + + // FIXME: use bounding-box-based frustum clipping info? + R_BuildPolygonFromSurface( psurf ); + R_ClipAndDrawPoly( pent->curstate.renderamt / 255, !!(psurf->flags & SURF_DRAWTURB), true ); + + } + } + + // put back world rotation and frustum clipping + // FIXME: R_RotateBmodel should just work off base_vxx + VectorCopy (base_vpn, vpn); + VectorCopy (base_vup, vup); + VectorCopy (base_vright, vright); + VectorCopy (oldorigin, modelorg); + R_TransformFrustum (); +} + + diff --git a/r_image.c b/r_image.c index 17a840fd..6a73e7e4 100644 --- a/r_image.c +++ b/r_image.c @@ -535,7 +535,6 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) if( j == 0 && tex->flags & TF_HAS_ALPHA ) tex->alpha_pixels = Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 64 ); - for(i = 0; i < height * width; i++ ) { unsigned int r, g, b, major, minor; @@ -560,6 +559,8 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) { unsigned int alpha = (pic->buffer[i * 4 + 3] * 8 / 256) << (16 - 3); tex->alpha_pixels[i] = (tex->pixels[j][i] >> 3) | alpha; + if( pic->buffer[i * 4 + 3] < 128 && FBitSet( pic->flags, IMAGE_ONEBIT_ALPHA ) ) + tex->pixels[j][i] = TRANSPARENT_COLOR; //0000 0011 0100 1001; } } diff --git a/r_local.h b/r_local.h index 5ed57284..fe032ad7 100644 --- a/r_local.h +++ b/r_local.h @@ -244,9 +244,11 @@ typedef struct typedef struct { + cl_entity_t *edge_entities[MAX_VISIBLE_PACKET]; // brush edge drawing cl_entity_t *solid_entities[MAX_VISIBLE_PACKET]; // opaque moving or alpha brushes cl_entity_t *trans_entities[MAX_VISIBLE_PACKET]; // translucent brushes cl_entity_t *beam_entities[MAX_VISIBLE_PACKET]; + uint num_edge_entities; uint num_solid_entities; uint num_trans_entities; uint num_beam_entities; @@ -799,7 +801,7 @@ extern cvar_t *r_showhull; #define PARTICLE_Z_CLIP 8.0 // !!! must be kept the same as in quakeasm.h !!! -#define TRANSPARENT_COLOR 0xFF +#define TRANSPARENT_COLOR 0x0349 //0xFF // !!! if this is changed, it must be changed in d_ifacea.h too !!! @@ -1027,7 +1029,7 @@ typedef struct { int nump; emitpoint_t *pverts; - byte *pixels; // image + pixel_t *pixels; // image int pixel_width; // image width int pixel_height; // image height vec3_t vup, vright, vpn; // in worldspace, for plane eq @@ -1282,6 +1284,7 @@ void R_AliasClipTriangle (finalvert_t *index0, finalvert_t *index1, finalvert_t void R_RotateBmodel (void); void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel, mnode_t *topnode); void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags, mnode_t *topnode); +void R_DrawBrushModel(cl_entity_t *pent); // // r_blitscreen.c @@ -1335,6 +1338,17 @@ void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]); void R_RenderTriangle( finalvert_t *fv1 , finalvert_t *fv2, finalvert_t *fv3 ); void R_SetupFinalVert( finalvert_t *fv, float x, float y, float z, int light, int s, int t ); +void RotatedBBox (vec3_t mins, vec3_t maxs, vec3_t angles, vec3_t tmins, vec3_t tmaxs); +int R_BmodelCheckBBox (float *minmaxs); + +// +// r_poly.c +// +void R_BuildPolygonFromSurface(msurface_t *fa); +void R_ClipAndDrawPoly( float alpha, qboolean isturbulent, qboolean textured ); + +void R_SetUpWorldTransform (void); + // // engine callbacks diff --git a/r_main.c b/r_main.c index 8bd9e029..e8a31207 100644 --- a/r_main.c +++ b/r_main.c @@ -407,6 +407,7 @@ void R_ClearScene( void ) tr.draw_list->num_solid_entities = 0; tr.draw_list->num_trans_entities = 0; tr.draw_list->num_beam_entities = 0; + tr.draw_list->num_edge_entities = 0; // clear the scene befor start new frame if( gEngfuncs.drawFuncs->R_ClearScene != NULL ) @@ -436,9 +437,17 @@ qboolean R_AddEntity( struct cl_entity_s *clent, int type ) if( type == ET_FRAGMENTED ) r_stats.c_client_ents++; - // debug: mark all solid - if( true ) // R_OpaqueEntity( clent )) + if( R_OpaqueEntity( clent )) { + if( clent->model->type == mod_brush ) + { + if( tr.draw_list->num_edge_entities >= MAX_VISIBLE_PACKET ) + return false; + + tr.draw_list->edge_entities[tr.draw_list->num_edge_entities] = clent; + tr.draw_list->num_edge_entities++; + return true; + } // opaque if( tr.draw_list->num_solid_entities >= MAX_VISIBLE_PACKET ) return false; @@ -1011,10 +1020,7 @@ void R_DrawEntitiesOnList( void ) d_aflatcolor = 0; tr.blend = 1.0f; // GL_CheckForErrors(); - // HACK: setup world transform - void R_AliasSetUpTransform (void); - RI.currententity = gEngfuncs.GetEntityByIndex(0); - R_AliasSetUpTransform(); + //RI.currententity = gEngfuncs.GetEntityByIndex(0); extern void (*d_pdrawspans)(void *); extern void R_PolysetFillSpans8 ( void * ); d_pdrawspans = R_PolysetFillSpans8; @@ -1031,12 +1037,13 @@ void R_DrawEntitiesOnList( void ) switch( RI.currentmodel->type ) { case mod_brush: - //R_DrawBrushModel( RI.currententity ); + R_DrawBrushModel( RI.currententity ); break; case mod_alias: //R_DrawAliasModel( RI.currententity ); break; case mod_studio: + R_SetUpWorldTransform(); R_DrawStudioModel( RI.currententity ); #if 0 // gradient debug (for colormap testing) @@ -1114,7 +1121,7 @@ void R_DrawEntitiesOnList( void ) tr.blend = gEngfuncs.CL_FxBlend( RI.currententity ) / 255.0f; else tr.blend = 1.0f; // draw as solid but sorted by distance - if( tr.blend <= 0.0f ) continue; + //if( tr.blend <= 0.0f ) continue; Assert( RI.currententity != NULL ); Assert( RI.currentmodel != NULL ); @@ -1122,13 +1129,14 @@ void R_DrawEntitiesOnList( void ) switch( RI.currentmodel->type ) { case mod_brush: - // R_DrawBrushModel( RI.currententity ); + R_DrawBrushModel( RI.currententity ); break; case mod_alias: //R_DrawAliasModel( RI.currententity ); break; case mod_studio: - // R_DrawStudioModel( RI.currententity ); + R_SetUpWorldTransform(); + R_DrawStudioModel( RI.currententity ); break; case mod_sprite: // R_DrawSpriteModel( RI.currententity ); @@ -1159,6 +1167,7 @@ void R_DrawEntitiesOnList( void ) // pglDisable( GL_BLEND ); // Trinity Render issues + R_SetUpWorldTransform(); if( !RI.onlyClientDraw ) R_DrawViewModel(); gEngfuncs.CL_ExtraUpdate(); @@ -1334,10 +1343,10 @@ void R_DrawBEntitiesOnList (void) insubmodel = true; //r_dlightframecount = r_framecount; - for( i = 0; i < tr.draw_list->num_solid_entities && !RI.onlyClientDraw; i++ ) + for( i = 0; i < tr.draw_list->num_edge_entities && !RI.onlyClientDraw; i++ ) { int k; - RI.currententity = tr.draw_list->solid_entities[i]; + RI.currententity = tr.draw_list->edge_entities[i]; RI.currentmodel = RI.currententity->model; if (!RI.currentmodel) continue; diff --git a/r_poly.c b/r_poly.c new file mode 100644 index 00000000..f3108db7 --- /dev/null +++ b/r_poly.c @@ -0,0 +1,1275 @@ +/* +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. + +*/ +#include +#include "r_local.h" + +#define AFFINE_SPANLET_SIZE 16 +#define AFFINE_SPANLET_SIZE_BITS 4 + +typedef struct +{ + int sent1; + pixel_t *pbase, *pdest; + short *pz; + int sent3; + fixed16_t s, t; + fixed16_t sstep, tstep; + int izi, izistep, izistep_times_2; + int spancount; + unsigned u, v; + int sent2; +} spanletvars_t; + +spanletvars_t s_spanletvars; + +static int r_polyblendcolor; + +static espan_t *s_polygon_spans; + +polydesc_t r_polydesc; + +msurface_t *r_alpha_surfaces; + +extern int *r_turb_turb; + +static int clip_current; +typedef vec_t vec5_t[5]; +vec5_t r_clip_verts[2][MAXWORKINGVERTS+2]; + +static int s_minindex, s_maxindex; + +static void R_DrawPoly( qboolean iswater ); + +/* +** R_DrawSpanletOpaque +*/ +void R_DrawSpanletOpaque( void ) +{ + unsigned btemp; + + do + { + unsigned ts, tt; + + ts = s_spanletvars.s >> 16; + tt = s_spanletvars.t >> 16; + + btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth); + if (btemp != TRANSPARENT_COLOR) + { + if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16)) + { + *s_spanletvars.pz = s_spanletvars.izi >> 16; + *s_spanletvars.pdest = btemp; + } + } + + s_spanletvars.izi += s_spanletvars.izistep; + s_spanletvars.pdest++; + s_spanletvars.pz++; + s_spanletvars.s += s_spanletvars.sstep; + s_spanletvars.t += s_spanletvars.tstep; + } while (--s_spanletvars.spancount > 0); +} + +/* +** R_DrawSpanletTurbulentStipple33 +*/ +void R_DrawSpanletTurbulentStipple33( void ) +{ + unsigned btemp; + int sturb, tturb; + pixel_t *pdest = s_spanletvars.pdest; + short *pz = s_spanletvars.pz; + int izi = s_spanletvars.izi; + + if ( s_spanletvars.v & 1 ) + { + s_spanletvars.pdest += s_spanletvars.spancount; + s_spanletvars.pz += s_spanletvars.spancount; + + if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE ) + s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS; + else + s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep; + + if ( s_spanletvars.u & 1 ) + { + izi += s_spanletvars.izistep; + s_spanletvars.s += s_spanletvars.sstep; + s_spanletvars.t += s_spanletvars.tstep; + + pdest++; + pz++; + s_spanletvars.spancount--; + } + + s_spanletvars.sstep *= 2; + s_spanletvars.tstep *= 2; + + while ( s_spanletvars.spancount > 0 ) + { + sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63; + tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63; + + btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) ); + + if ( *pz <= ( izi >> 16 ) ) + *pdest = btemp; + + izi += s_spanletvars.izistep_times_2; + s_spanletvars.s += s_spanletvars.sstep; + s_spanletvars.t += s_spanletvars.tstep; + + pdest += 2; + pz += 2; + + s_spanletvars.spancount -= 2; + } + } +} + +/* +** R_DrawSpanletTurbulentStipple66 +*/ +void R_DrawSpanletTurbulentStipple66( void ) +{ + unsigned btemp; + int sturb, tturb; + pixel_t *pdest = s_spanletvars.pdest; + short *pz = s_spanletvars.pz; + int izi = s_spanletvars.izi; + + if ( !( s_spanletvars.v & 1 ) ) + { + s_spanletvars.pdest += s_spanletvars.spancount; + s_spanletvars.pz += s_spanletvars.spancount; + + if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE ) + s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS; + else + s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep; + + if ( s_spanletvars.u & 1 ) + { + izi += s_spanletvars.izistep; + s_spanletvars.s += s_spanletvars.sstep; + s_spanletvars.t += s_spanletvars.tstep; + + pdest++; + pz++; + s_spanletvars.spancount--; + } + + s_spanletvars.sstep *= 2; + s_spanletvars.tstep *= 2; + + while ( s_spanletvars.spancount > 0 ) + { + sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63; + tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63; + + btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) ); + + if ( *pz <= ( izi >> 16 ) ) + *pdest = btemp; + + izi += s_spanletvars.izistep_times_2; + s_spanletvars.s += s_spanletvars.sstep; + s_spanletvars.t += s_spanletvars.tstep; + + pdest += 2; + pz += 2; + + s_spanletvars.spancount -= 2; + } + } + else + { + s_spanletvars.pdest += s_spanletvars.spancount; + s_spanletvars.pz += s_spanletvars.spancount; + + if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE ) + s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS; + else + s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep; + + while ( s_spanletvars.spancount > 0 ) + { + sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63; + tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63; + + btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) ); + + if ( *pz <= ( izi >> 16 ) ) + *pdest = btemp; + + izi += s_spanletvars.izistep; + s_spanletvars.s += s_spanletvars.sstep; + s_spanletvars.t += s_spanletvars.tstep; + + pdest++; + pz++; + + s_spanletvars.spancount--; + } + } +} + +/* +** R_DrawSpanletTurbulentBlended +*/ +void R_DrawSpanletTurbulentBlended66( void ) +{ + unsigned btemp; + int sturb, tturb; + + do + { + sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63; + tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63; + + btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) ); + + if ( *s_spanletvars.pz <= ( s_spanletvars.izi >> 16 ) ) + { + pixel_t screen = *s_spanletvars.pdest; + pixel_t src = btemp; + byte alpha = 4; + *s_spanletvars.pdest = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0x7f) >> 3 | ((src & 0xff)); + } + + s_spanletvars.izi += s_spanletvars.izistep; + s_spanletvars.pdest++; + s_spanletvars.pz++; + s_spanletvars.s += s_spanletvars.sstep; + s_spanletvars.t += s_spanletvars.tstep; + + } while ( --s_spanletvars.spancount > 0 ); +} + +void R_DrawSpanletTurbulentBlended33( void ) +{ + unsigned btemp; + int sturb, tturb; + + do + { + sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63; + tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63; + + btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) ); + + if ( *s_spanletvars.pz <= ( s_spanletvars.izi >> 16 ) ) + { + pixel_t screen = *s_spanletvars.pdest; + pixel_t src = btemp; + byte alpha = 4; + *s_spanletvars.pdest = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0x7f) >> 3 | ((src & 0xff)); + } + + s_spanletvars.izi += s_spanletvars.izistep; + s_spanletvars.pdest++; + s_spanletvars.pz++; + s_spanletvars.s += s_spanletvars.sstep; + s_spanletvars.t += s_spanletvars.tstep; + + } while ( --s_spanletvars.spancount > 0 ); +} + +/* +** R_DrawSpanlet33 +*/ +void R_DrawSpanlet33( void ) +{ + unsigned btemp; + + do + { + unsigned ts, tt; + + ts = s_spanletvars.s >> 16; + tt = s_spanletvars.t >> 16; + + btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth); + + if ( btemp != 255 ) + { + if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16)) + { + pixel_t screen = *s_spanletvars.pdest; + pixel_t src = btemp; + byte alpha = 4; + *s_spanletvars.pdest = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0x7f) >> 3 | ((src & 0xff)); + } + + } + + s_spanletvars.izi += s_spanletvars.izistep; + s_spanletvars.pdest++; + s_spanletvars.pz++; + s_spanletvars.s += s_spanletvars.sstep; + s_spanletvars.t += s_spanletvars.tstep; + } while (--s_spanletvars.spancount > 0); +} + +void R_DrawSpanletConstant33( void ) +{ + do + { + if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16)) + { + *s_spanletvars.pdest = vid.alphamap[r_polyblendcolor+*s_spanletvars.pdest*256]; + } + + s_spanletvars.izi += s_spanletvars.izistep; + s_spanletvars.pdest++; + s_spanletvars.pz++; + } while (--s_spanletvars.spancount > 0); +} + +/* +** R_DrawSpanlet66 +*/ +void R_DrawSpanlet66( void ) +{ + unsigned btemp; + + do + { + unsigned ts, tt; + + ts = s_spanletvars.s >> 16; + tt = s_spanletvars.t >> 16; + + btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth); + + if ( btemp != 255 ) + { + if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16)) + { + pixel_t screen = *s_spanletvars.pdest; + pixel_t src = btemp; + byte alpha = 4; + *s_spanletvars.pdest = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0x7f) >> 3 | ((src & 0xff)); + } + + } + + s_spanletvars.izi += s_spanletvars.izistep; + s_spanletvars.pdest++; + s_spanletvars.pz++; + s_spanletvars.s += s_spanletvars.sstep; + s_spanletvars.t += s_spanletvars.tstep; + } while (--s_spanletvars.spancount > 0); +} + +/* +** R_DrawSpanlet33Stipple +*/ +void R_DrawSpanlet33Stipple( void ) +{ + unsigned btemp; + pixel_t *pdest = s_spanletvars.pdest; + short *pz = s_spanletvars.pz; + int izi = s_spanletvars.izi; + + if ( r_polydesc.stipple_parity ^ ( s_spanletvars.v & 1 ) ) + { + s_spanletvars.pdest += s_spanletvars.spancount; + s_spanletvars.pz += s_spanletvars.spancount; + + if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE ) + s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS; + else + s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep; + + if ( r_polydesc.stipple_parity ^ ( s_spanletvars.u & 1 ) ) + { + izi += s_spanletvars.izistep; + s_spanletvars.s += s_spanletvars.sstep; + s_spanletvars.t += s_spanletvars.tstep; + + pdest++; + pz++; + s_spanletvars.spancount--; + } + + s_spanletvars.sstep *= 2; + s_spanletvars.tstep *= 2; + + while ( s_spanletvars.spancount > 0 ) + { + unsigned s = s_spanletvars.s >> 16; + unsigned t = s_spanletvars.t >> 16; + + btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) ); + + if ( btemp != 255 ) + { + if ( *pz <= ( izi >> 16 ) ) + *pdest = btemp; + } + + izi += s_spanletvars.izistep_times_2; + s_spanletvars.s += s_spanletvars.sstep; + s_spanletvars.t += s_spanletvars.tstep; + + pdest += 2; + pz += 2; + + s_spanletvars.spancount -= 2; + } + } +} + +/* +** R_DrawSpanlet66Stipple +*/ +void R_DrawSpanlet66Stipple( void ) +{ + unsigned btemp; + pixel_t *pdest = s_spanletvars.pdest; + short *pz = s_spanletvars.pz; + int izi = s_spanletvars.izi; + + s_spanletvars.pdest += s_spanletvars.spancount; + s_spanletvars.pz += s_spanletvars.spancount; + + if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE ) + s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS; + else + s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep; + + if ( r_polydesc.stipple_parity ^ ( s_spanletvars.v & 1 ) ) + { + if ( r_polydesc.stipple_parity ^ ( s_spanletvars.u & 1 ) ) + { + izi += s_spanletvars.izistep; + s_spanletvars.s += s_spanletvars.sstep; + s_spanletvars.t += s_spanletvars.tstep; + + pdest++; + pz++; + s_spanletvars.spancount--; + } + + s_spanletvars.sstep *= 2; + s_spanletvars.tstep *= 2; + + while ( s_spanletvars.spancount > 0 ) + { + unsigned s = s_spanletvars.s >> 16; + unsigned t = s_spanletvars.t >> 16; + + btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) ); + + if ( btemp != 255 ) + { + if ( *pz <= ( izi >> 16 ) ) + *pdest = btemp; + } + + izi += s_spanletvars.izistep_times_2; + s_spanletvars.s += s_spanletvars.sstep; + s_spanletvars.t += s_spanletvars.tstep; + + pdest += 2; + pz += 2; + + s_spanletvars.spancount -= 2; + } + } + else + { + while ( s_spanletvars.spancount > 0 ) + { + unsigned s = s_spanletvars.s >> 16; + unsigned t = s_spanletvars.t >> 16; + + btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) ); + + if ( btemp != 255 ) + { + if ( *pz <= ( izi >> 16 ) ) + *pdest = btemp; + } + + izi += s_spanletvars.izistep; + s_spanletvars.s += s_spanletvars.sstep; + s_spanletvars.t += s_spanletvars.tstep; + + pdest++; + pz++; + + s_spanletvars.spancount--; + } + } +} + +/* +** R_ClipPolyFace +** +** Clips the winding at clip_verts[clip_current] and changes clip_current +** Throws out the back side +*/ +int R_ClipPolyFace (int nump, clipplane_t *pclipplane) +{ + int i, outcount; + float dists[MAXWORKINGVERTS+3]; + float frac, clipdist, *pclipnormal; + float *in, *instep, *outstep, *vert2; + + clipdist = pclipplane->dist; + pclipnormal = pclipplane->normal; + +// calc dists + if (clip_current) + { + in = r_clip_verts[1][0]; + outstep = r_clip_verts[0][0]; + clip_current = 0; + } + else + { + in = r_clip_verts[0][0]; + outstep = r_clip_verts[1][0]; + clip_current = 1; + } + + instep = in; + for (i=0 ; i= 0) + { + memcpy (outstep, instep, sizeof (vec5_t)); + outstep += sizeof (vec5_t) / sizeof (float); + outcount++; + } + + if (dists[i] == 0 || dists[i+1] == 0) + continue; + + if ( (dists[i] > 0) == (dists[i+1] > 0) ) + continue; + + // split it into a new vertex + frac = dists[i] / (dists[i] - dists[i+1]); + + vert2 = instep + sizeof (vec5_t) / sizeof (float); + + outstep[0] = instep[0] + frac*(vert2[0] - instep[0]); + outstep[1] = instep[1] + frac*(vert2[1] - instep[1]); + outstep[2] = instep[2] + frac*(vert2[2] - instep[2]); + outstep[3] = instep[3] + frac*(vert2[3] - instep[3]); + outstep[4] = instep[4] + frac*(vert2[4] - instep[4]); + + outstep += sizeof (vec5_t) / sizeof (float); + outcount++; + } + + return outcount; +} + +/* +** R_PolygonDrawSpans +*/ +void R_PolygonDrawSpans(espan_t *pspan, qboolean iswater ) +{ + int count; + fixed16_t snext, tnext; + float sdivz, tdivz, zi, z, du, dv, spancountminus1; + float sdivzspanletstepu, tdivzspanletstepu, zispanletstepu; + + s_spanletvars.pbase = cacheblock; + + if ( iswater ) + r_turb_turb = sintable + ((int)(gpGlobals->time*SPEED)&(CYCLE-1)); + + sdivzspanletstepu = d_sdivzstepu * AFFINE_SPANLET_SIZE; + tdivzspanletstepu = d_tdivzstepu * AFFINE_SPANLET_SIZE; + zispanletstepu = d_zistepu * AFFINE_SPANLET_SIZE; + +// we count on FP exceptions being turned off to avoid range problems + s_spanletvars.izistep = (int)(d_zistepu * 0x8000 * 0x10000); + s_spanletvars.izistep_times_2 = s_spanletvars.izistep * 2; + + s_spanletvars.pz = 0; + + do + { + s_spanletvars.pdest = d_viewbuffer + ( d_scantable[pspan->v] /*r_screenwidth * pspan->v*/) + pspan->u; + s_spanletvars.pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; + s_spanletvars.u = pspan->u; + s_spanletvars.v = pspan->v; + //printf("%p %p %d %d\n", s_spanletvars.pdest, s_spanletvars.pz, s_spanletvars.u, s_spanletvars.v); + + count = pspan->count; + + if (count <= 0) + goto NextSpan; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float)pspan->u; + dv = (float)pspan->v; + + sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; + tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; + + zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + // we count on FP exceptions being turned off to avoid range problems + s_spanletvars.izi = (int)(zi * 0x8000 * 0x10000); + + s_spanletvars.s = (int)(sdivz * z) + sadjust; + s_spanletvars.t = (int)(tdivz * z) + tadjust; + + if ( !iswater ) + { + if (s_spanletvars.s > bbextents) + s_spanletvars.s = bbextents; + else if (s_spanletvars.s < 0) + s_spanletvars.s = 0; + + if (s_spanletvars.t > bbextentt) + s_spanletvars.t = bbextentt; + else if (s_spanletvars.t < 0) + s_spanletvars.t = 0; + } + + do + { + // calculate s and t at the far end of the span + if (count >= AFFINE_SPANLET_SIZE ) + s_spanletvars.spancount = AFFINE_SPANLET_SIZE; + else + s_spanletvars.spancount = count; + + count -= s_spanletvars.spancount; + + if (count) + { + // calculate s/z, t/z, zi->fixed s and t at far end of span, + // calculate s and t steps across span by shifting + sdivz += sdivzspanletstepu; + tdivz += tdivzspanletstepu; + zi += zispanletstepu; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + + snext = (int)(sdivz * z) + sadjust; + tnext = (int)(tdivz * z) + tadjust; + + if ( !iswater ) + { + if (snext > bbextents) + snext = bbextents; + else if (snext < AFFINE_SPANLET_SIZE) + snext = AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < AFFINE_SPANLET_SIZE) + tnext = AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps + } + + s_spanletvars.sstep = (snext - s_spanletvars.s) >> AFFINE_SPANLET_SIZE_BITS; + s_spanletvars.tstep = (tnext - s_spanletvars.t) >> AFFINE_SPANLET_SIZE_BITS; + } + else + { + // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so + // can't step off polygon), clamp, calculate s and t steps across + // span by division, biasing steps low so we don't run off the + // texture + spancountminus1 = (float)(s_spanletvars.spancount - 1); + sdivz += d_sdivzstepu * spancountminus1; + tdivz += d_tdivzstepu * spancountminus1; + zi += d_zistepu * spancountminus1; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + snext = (int)(sdivz * z) + sadjust; + tnext = (int)(tdivz * z) + tadjust; + + if ( !iswater ) + { + if (snext > bbextents) + snext = bbextents; + else if (snext < AFFINE_SPANLET_SIZE) + snext = AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < AFFINE_SPANLET_SIZE) + tnext = AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps + } + + if (s_spanletvars.spancount > 1) + { + s_spanletvars.sstep = (snext - s_spanletvars.s) / (s_spanletvars.spancount - 1); + s_spanletvars.tstep = (tnext - s_spanletvars.t) / (s_spanletvars.spancount - 1); + } + } + + if ( iswater ) + { + s_spanletvars.s = s_spanletvars.s & ((CYCLE<<16)-1); + s_spanletvars.t = s_spanletvars.t & ((CYCLE<<16)-1); + } + + r_polydesc.drawspanlet(); + + s_spanletvars.s = snext; + s_spanletvars.t = tnext; + + } while (count > 0); + +NextSpan: + pspan++; + + } while (pspan->count != DS_SPAN_LIST_END); +} + +/* +** +** R_PolygonScanLeftEdge +** +** Goes through the polygon and scans the left edge, filling in +** screen coordinate data for the spans +*/ +void R_PolygonScanLeftEdge (void) +{ + int i, v, itop, ibottom, lmaxindex; + emitpoint_t *pvert, *pnext; + espan_t *pspan; + float du, dv, vtop, vbottom, slope; + fixed16_t u, u_step; + + pspan = s_polygon_spans; + i = s_minindex; + if (i == 0) + i = r_polydesc.nump; + + lmaxindex = s_maxindex; + if (lmaxindex == 0) + lmaxindex = r_polydesc.nump; + + vtop = ceil (r_polydesc.pverts[i].v); + + do + { + pvert = &r_polydesc.pverts[i]; + pnext = pvert - 1; + + vbottom = ceil (pnext->v); + + if (vtop < vbottom) + { + du = pnext->u - pvert->u; + dv = pnext->v - pvert->v; + + slope = du / dv; + u_step = (int)(slope * 0x10000); + // adjust u to ceil the integer portion + u = (int)((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) + + (0x10000 - 1); + itop = (int)vtop; + ibottom = (int)vbottom; + + for (v=itop ; vu = u >> 16; + pspan->v = v; + u += u_step; + pspan++; + } + } + + vtop = vbottom; + + i--; + if (i == 0) + i = r_polydesc.nump; + + } while (i != lmaxindex); +} + +/* +** R_PolygonScanRightEdge +** +** Goes through the polygon and scans the right edge, filling in +** count values. +*/ +void R_PolygonScanRightEdge (void) +{ + int i, v, itop, ibottom; + emitpoint_t *pvert, *pnext; + espan_t *pspan; + float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext; + fixed16_t u, u_step; + + pspan = s_polygon_spans; + i = s_minindex; + + vvert = r_polydesc.pverts[i].v; + if (vvert < RI.fvrecty_adj) + vvert = RI.fvrecty_adj; + if (vvert > RI.fvrectbottom_adj) + vvert = RI.fvrectbottom_adj; + + vtop = ceil (vvert); + + do + { + pvert = &r_polydesc.pverts[i]; + pnext = pvert + 1; + + vnext = pnext->v; + if (vnext < RI.fvrecty_adj) + vnext = RI.fvrecty_adj; + if (vnext > RI.fvrectbottom_adj) + vnext = RI.fvrectbottom_adj; + + vbottom = ceil (vnext); + + if (vtop < vbottom) + { + uvert = pvert->u; + if (uvert < RI.fvrectx_adj) + uvert = RI.fvrectx_adj; + if (uvert > RI.fvrectright_adj) + uvert = RI.fvrectright_adj; + + unext = pnext->u; + if (unext < RI.fvrectx_adj) + unext = RI.fvrectx_adj; + if (unext > RI.fvrectright_adj) + unext = RI.fvrectright_adj; + + du = unext - uvert; + dv = vnext - vvert; + slope = du / dv; + u_step = (int)(slope * 0x10000); + // adjust u to ceil the integer portion + u = (int)((uvert + (slope * (vtop - vvert))) * 0x10000) + + (0x10000 - 1); + itop = (int)vtop; + ibottom = (int)vbottom; + + for (v=itop ; vcount = (u >> 16) - pspan->u; + u += u_step; + pspan++; + } + } + + vtop = vbottom; + vvert = vnext; + + i++; + if (i == r_polydesc.nump) + i = 0; + + } while (i != s_maxindex); + + pspan->count = DS_SPAN_LIST_END; // mark the end of the span list +} + +/* +** R_ClipAndDrawPoly +*/ +void R_ClipAndDrawPoly( float alpha, qboolean isturbulent, qboolean textured ) +{ + emitpoint_t outverts[MAXWORKINGVERTS+3], *pout; + float *pv; + int i, nump; + float scale; + vec3_t transformed, local; + + if ( !textured ) + { + r_polydesc.drawspanlet = R_DrawSpanletConstant33; + } + else + { + + /* + ** choose the correct spanlet routine based on alpha + */ + if ( alpha == 1 ) + { + // isturbulent is ignored because we know that turbulent surfaces + // can't be opaque + r_polydesc.drawspanlet = R_DrawSpanletOpaque; + } + else + { + if ( sw_stipplealpha->value ) + { + if ( isturbulent ) + { + if ( alpha > 0.33 ) + r_polydesc.drawspanlet = R_DrawSpanletTurbulentStipple66; + else + r_polydesc.drawspanlet = R_DrawSpanletTurbulentStipple33; + } + else + { + if ( alpha > 0.33 ) + r_polydesc.drawspanlet = R_DrawSpanlet66Stipple; + else + r_polydesc.drawspanlet = R_DrawSpanlet33Stipple; + } + } + else + { + if ( isturbulent ) + { + if ( alpha > 0.33 ) + r_polydesc.drawspanlet = R_DrawSpanletTurbulentBlended66; + else + r_polydesc.drawspanlet = R_DrawSpanletTurbulentBlended33; + } + else + { + if ( alpha > 0.33 ) + r_polydesc.drawspanlet = R_DrawSpanlet66; + else + r_polydesc.drawspanlet = R_DrawSpanlet33; + } + } + } + } + + // clip to the frustum in worldspace + nump = r_polydesc.nump; + clip_current = 0; + + for (i=0 ; i<4 ; i++) + { + nump = R_ClipPolyFace (nump, &view_clipplanes[i]); + if (nump < 3) + return; + if (nump > MAXWORKINGVERTS) + gEngfuncs.Host_Error( "R_ClipAndDrawPoly: too many points: %d", nump ); + } + +// transform vertices into viewspace and project + pv = &r_clip_verts[clip_current][0][0]; + + for (i=0 ; izi = 1.0 / transformed[2]; + + pout->s = pv[3]; + pout->t = pv[4]; + + scale = xscale * pout->zi; + pout->u = (xcenter + scale * transformed[0]); + + scale = yscale * pout->zi; + pout->v = (ycenter - scale * transformed[1]); + + pv += sizeof (vec5_t) / sizeof (pv); + } + +// draw it + r_polydesc.nump = nump; + r_polydesc.pverts = outverts; + + R_DrawPoly( isturbulent ); +} + +/* +** R_BuildPolygonFromSurface +*/ +void R_BuildPolygonFromSurface(msurface_t *fa) +{ + int i, lindex, lnumverts; + medge_t *pedges, *r_pedge; + int vertpage; + float *vec; + vec5_t *pverts; + float tmins[2] = { 0, 0 }; + + r_polydesc.nump = 0; + + // reconstruct the polygon + pedges = RI.currentmodel->edges; + lnumverts = fa->numedges; + vertpage = 0; + + pverts = r_clip_verts[0]; + + for (i=0 ; isurfedges[fa->firstedge + i]; + + if (lindex > 0) + { + r_pedge = &pedges[lindex]; + vec = RI.currentmodel->vertexes[r_pedge->v[0]].position; + } + else + { + r_pedge = &pedges[-lindex]; + vec = RI.currentmodel->vertexes[r_pedge->v[1]].position; + } + + VectorCopy (vec, pverts[i] ); + } + + VectorCopy( fa->texinfo->vecs[0], r_polydesc.vright ); + VectorCopy( fa->texinfo->vecs[1], r_polydesc.vup ); + VectorCopy( fa->plane->normal, r_polydesc.vpn ); + VectorCopy( r_origin, r_polydesc.viewer_position ); + + + if ( fa->flags & SURF_PLANEBACK ) + { + VectorSubtract( vec3_origin, r_polydesc.vpn, r_polydesc.vpn ); + } + + // todo: water + if ( fa->texinfo->flags & SURF_DRAWTURB ) + { + image_t *pic = R_GetTexture(fa->texinfo->texture->gl_texturenum); + r_polydesc.pixels = pic->pixels[0]; + r_polydesc.pixel_width = pic->width; + r_polydesc.pixel_height = pic->height; + } + else + { + surfcache_t *scache; + + scache = D_CacheSurface( fa, 0 ); + + r_polydesc.pixels = scache->data; + r_polydesc.pixel_width = scache->width; + r_polydesc.pixel_height = scache->height; + + tmins[0] = fa->texturemins[0]; + tmins[1] = fa->texturemins[1]; + } + + r_polydesc.dist = DotProduct( r_polydesc.vpn, pverts[0] ); + + r_polydesc.s_offset = fa->texinfo->vecs[0][3] - tmins[0]; + r_polydesc.t_offset = fa->texinfo->vecs[1][3] - tmins[1]; + + // scrolling texture addition + // todo: conveyors + if (fa->flags & SURF_CONVEYOR) + { + r_polydesc.s_offset += -128 * ( (gpGlobals->time*0.25) - (int)(gpGlobals->time*0.25) ); + } + + r_polydesc.nump = lnumverts; +} + +/* +** R_PolygonCalculateGradients +*/ +void R_PolygonCalculateGradients (void) +{ + vec3_t p_normal, p_saxis, p_taxis; + float distinv; + + TransformVector (r_polydesc.vpn, p_normal); + TransformVector (r_polydesc.vright, p_saxis); + TransformVector (r_polydesc.vup, p_taxis); + + distinv = 1.0 / (-(DotProduct (r_polydesc.viewer_position, r_polydesc.vpn)) + r_polydesc.dist ); + + d_sdivzstepu = p_saxis[0] * xscaleinv; + d_sdivzstepv = -p_saxis[1] * yscaleinv; + d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu - ycenter * d_sdivzstepv; + + d_tdivzstepu = p_taxis[0] * xscaleinv; + d_tdivzstepv = -p_taxis[1] * yscaleinv; + d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu - ycenter * d_tdivzstepv; + + d_zistepu = p_normal[0] * xscaleinv * distinv; + d_zistepv = -p_normal[1] * yscaleinv * distinv; + d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu - ycenter * d_zistepv; + + sadjust = (fixed16_t) ( ( DotProduct( r_polydesc.viewer_position, r_polydesc.vright) + r_polydesc.s_offset ) * 0x10000 ); + tadjust = (fixed16_t) ( ( DotProduct( r_polydesc.viewer_position, r_polydesc.vup ) + r_polydesc.t_offset ) * 0x10000 ); + +// -1 (-epsilon) so we never wander off the edge of the texture + bbextents = (r_polydesc.pixel_width << 16) - 1; + bbextentt = (r_polydesc.pixel_height << 16) - 1; +} + +/* +** R_DrawPoly +** +** Polygon drawing function. Uses the polygon described in r_polydesc +** to calculate edges and gradients, then renders the resultant spans. +** +** This should NOT be called externally since it doesn't do clipping! +*/ +static void R_DrawPoly( qboolean iswater ) +{ + int i, nump; + float ymin, ymax; + emitpoint_t *pverts; + espan_t spans[MAXHEIGHT+1]; + + s_polygon_spans = spans; + +// find the top and bottom vertices, and make sure there's at least one scan to +// draw + ymin = 999999.9; + ymax = -999999.9; + pverts = r_polydesc.pverts; + + for (i=0 ; iv < ymin) + { + ymin = pverts->v; + s_minindex = i; + } + + if (pverts->v > ymax) + { + ymax = pverts->v; + s_maxindex = i; + } + + pverts++; + } + + ymin = ceil (ymin); + ymax = ceil (ymax); + + if (ymin >= ymax) + return; // doesn't cross any scans at all + + cachewidth = r_polydesc.pixel_width; + cacheblock = r_polydesc.pixels; + +// copy the first vertex to the last vertex, so we don't have to deal with +// wrapping + nump = r_polydesc.nump; + pverts = r_polydesc.pverts; + pverts[nump] = pverts[0]; + + R_PolygonCalculateGradients (); + R_PolygonScanLeftEdge (); + R_PolygonScanRightEdge (); + + R_PolygonDrawSpans( s_polygon_spans, iswater ); +} + +/* +** R_DrawAlphaSurfaces +*/ +void R_DrawAlphaSurfaces( void ) +{ + + // is this used in HL? world does not seems to have transparent surfaces + // world water does not have alpha without special compilers + msurface_t *s = r_alpha_surfaces; + + RI.currentmodel = WORLDMODEL; + + modelorg[0] = -r_origin[0]; + modelorg[1] = -r_origin[1]; + modelorg[2] = -r_origin[2]; + + while ( s ) + { + R_BuildPolygonFromSurface( s ); + +// if (s->texinfo->flags & SURF_TRANS66) +// R_ClipAndDrawPoly( 0.60f, ( s->texinfo->flags & SURF_WARP) != 0, true ); +// else +// R_ClipAndDrawPoly( 0.30f, ( s->texinfo->flags & SURF_WARP) != 0, true ); + R_ClipAndDrawPoly( 1, false, true ); + + s = s->texturechain; // s->nextalphasurface; + } + + r_alpha_surfaces = NULL; +} + +/* +** R_IMFlatShadedQuad +*/ +void R_IMFlatShadedQuad( vec3_t a, vec3_t b, vec3_t c, vec3_t d, int color, float alpha ) +{ + vec3_t s0, s1; + + r_polydesc.nump = 4; + VectorCopy( r_origin, r_polydesc.viewer_position ); + + VectorCopy( a, r_clip_verts[0][0] ); + VectorCopy( b, r_clip_verts[0][1] ); + VectorCopy( c, r_clip_verts[0][2] ); + VectorCopy( d, r_clip_verts[0][3] ); + + r_clip_verts[0][0][3] = 0; + r_clip_verts[0][1][3] = 0; + r_clip_verts[0][2][3] = 0; + r_clip_verts[0][3][3] = 0; + + r_clip_verts[0][0][4] = 0; + r_clip_verts[0][1][4] = 0; + r_clip_verts[0][2][4] = 0; + r_clip_verts[0][3][4] = 0; + + VectorSubtract( d, c, s0 ); + VectorSubtract( c, b, s1 ); + CrossProduct( s0, s1, r_polydesc.vpn ); + VectorNormalize( r_polydesc.vpn ); + + r_polydesc.dist = DotProduct( r_polydesc.vpn, r_clip_verts[0][0] ); + + r_polyblendcolor = color; + + R_ClipAndDrawPoly( alpha, false, false ); +} + diff --git a/r_surf.c b/r_surf.c index cd032d3b..65011ae1 100644 --- a/r_surf.c +++ b/r_surf.c @@ -582,6 +582,8 @@ void R_DrawSurfaceBlock8_mip0 (void) { pix = psource[b]; prowdest[b] = BLEND_LM(pix, light); + if( pix == TRANSPARENT_COLOR ) + prowdest[b] = TRANSPARENT_COLOR; // pix; //((unsigned char *)vid.colormap) @@ -1069,6 +1071,8 @@ void R_DrawSurfaceDecals() if( alpha < 7) // && (vid.rendermode == kRenderTransAlpha || vid.rendermode == kRenderTransTexture ) ) { pixel_t screen = dest[u]; // | 0xff & screen & src ; + if( screen == TRANSPARENT_COLOR ) + continue; dest[u] = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0x7f) >> 3 | ((src & 0xff)); } diff --git a/r_trialias.c b/r_trialias.c index 0233dda3..6c92eeac 100644 --- a/r_trialias.c +++ b/r_trialias.c @@ -78,6 +78,78 @@ void VectorInverse (vec3_t v) v[2] = -v[2]; } +/* +================ +R_SetUpWorldTransform +================ +*/ +void R_SetUpWorldTransform (void) +{ + int i; + static float viewmatrix[3][4]; + vec3_t angles; + +// TODO: should really be stored with the entity instead of being reconstructed +// TODO: should use a look-up table +// TODO: could cache lazily, stored in the entity +// + + s_ziscale = (float)0x8000 * (float)0x10000; + angles[ROLL] = 0; + angles[PITCH] = 0; + angles[YAW] = 0; + AngleVectors( angles, s_alias_forward, s_alias_right, s_alias_up ); + +// TODO: can do this with simple matrix rearrangement + + memset( aliasworldtransform, 0, sizeof( aliasworldtransform ) ); + memset( aliasoldworldtransform, 0, sizeof( aliasworldtransform ) ); + + for (i=0 ; i<3 ; i++) + { + aliasoldworldtransform[i][0] = aliasworldtransform[i][0] = s_alias_forward[i]; + aliasoldworldtransform[i][0] = aliasworldtransform[i][1] = -s_alias_right[i]; + aliasoldworldtransform[i][0] = aliasworldtransform[i][2] = s_alias_up[i]; + } + + aliasworldtransform[0][3] = -r_origin[0]; + aliasworldtransform[1][3] = -r_origin[1]; + aliasworldtransform[2][3] = -r_origin[2]; + + //aliasoldworldtransform[0][3] = RI.currententity->oldorigin[0]-r_origin[0]; + //aliasoldworldtransform[1][3] = RI.currententity->oldorigin[1]-r_origin[1]; + //aliasoldworldtransform[2][3] = RI.currententity->oldorigin[2]-r_origin[2]; + +// FIXME: can do more efficiently than full concatenation +// memcpy( rotationmatrix, t2matrix, sizeof( rotationmatrix ) ); + +// R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix); + +// TODO: should be global, set when vright, etc., set + VectorCopy (vright, viewmatrix[0]); + VectorCopy (vup, viewmatrix[1]); + VectorInverse (viewmatrix[1]); + //VectorScale(viewmatrix[1], -1, viewmatrix[1]); + VectorCopy (vpn, viewmatrix[2]); + + viewmatrix[0][3] = 0; + viewmatrix[1][3] = 0; + viewmatrix[2][3] = 0; + +// memcpy( aliasworldtransform, rotationmatrix, sizeof( aliastransform ) ); + + R_ConcatTransforms (viewmatrix, aliasworldtransform, aliastransform); + + aliasworldtransform[0][3] = 0; + aliasworldtransform[1][3] = 0; + aliasworldtransform[2][3] = 0; + + //aliasoldworldtransform[0][3] = RI.currententity->oldorigin[0]; + //aliasoldworldtransform[1][3] = RI.currententity->oldorigin[1]; + //aliasoldworldtransform[2][3] = RI.currententity->oldorigin[2]; +} + + /* ================ R_AliasSetUpTransform From eeda097603385ffe08d932ec7f999b331618dd84 Mon Sep 17 00:00:00 2001 From: mittorn Date: Fri, 29 Mar 2019 02:13:45 +0700 Subject: [PATCH 039/115] ref_soft: Fix water --- r_main.c | 17 +++++++++++++++++ r_poly.c | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/r_main.c b/r_main.c index e8a31207..f606d33e 100644 --- a/r_main.c +++ b/r_main.c @@ -1903,6 +1903,22 @@ void R_NewMap (void) } } +/* +================ +R_InitTurb +================ +*/ +void R_InitTurb (void) +{ + int i; + + for (i=0 ; i<1280 ; i++) + { + sintable[i] = AMP + sin(i*3.14159*2/CYCLE)*AMP; + intsintable[i] = AMP2 + sin(i*3.14159*2/CYCLE)*AMP2; // AMP2, not 20 + blanktable[i] = 0; //PGM + } +} @@ -1967,6 +1983,7 @@ qboolean R_Init() view_clipplanes[1].leftedge = view_clipplanes[2].leftedge =view_clipplanes[3].leftedge = false; view_clipplanes[0].rightedge = view_clipplanes[2].rightedge = view_clipplanes[3].rightedge = false; R_StudioInit(); + R_InitTurb(); return true; } diff --git a/r_poly.c b/r_poly.c index f3108db7..129793bf 100644 --- a/r_poly.c +++ b/r_poly.c @@ -1072,7 +1072,7 @@ void R_BuildPolygonFromSurface(msurface_t *fa) } // todo: water - if ( fa->texinfo->flags & SURF_DRAWTURB ) + if ( fa->flags & SURF_DRAWTURB ) { image_t *pic = R_GetTexture(fa->texinfo->texture->gl_texturenum); r_polydesc.pixels = pic->pixels[0]; From 56ef16b0f9fc6663b5c2954c7f8361eb8298950d Mon Sep 17 00:00:00 2001 From: mittorn Date: Fri, 29 Mar 2019 03:52:08 +0700 Subject: [PATCH 040/115] ref_soft: enable stiple alpha by default, cache conveyors --- r_edge.c | 25 ++++++++++++++++--------- r_main.c | 2 +- r_poly.c | 16 ++++++++-------- r_surf.c | 22 ++++++++++++++++++++++ 4 files changed, 47 insertions(+), 18 deletions(-) diff --git a/r_edge.c b/r_edge.c index 59443524..c5b4b006 100644 --- a/r_edge.c +++ b/r_edge.c @@ -847,14 +847,15 @@ void D_CalcGradients (msurface_t *pface) tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - ((pface->texturemins[1] << 16) >> miplevel) + pface->texinfo->vecs[1][3]*t; -#if 0 +#if 1 // PGM - changing flow speed for non-warping textures. - if (pface->texinfo->flags & SURF_FLOWING) + if (pface->flags & SURF_CONVEYOR) { - if(pface->texinfo->flags & SURF_WARP) - sadjust += 0x10000 * (-128 * ( (r_newrefdef.time * 0.25) - (int)(r_newrefdef.time * 0.25) )); + + if(pface->flags & SURF_DRAWTURB) + sadjust += 0x10000 * (-128 * ( (gpGlobals->time * 0.25) - (int)(gpGlobals->time * 0.25) )); else - sadjust += 0x10000 * (-128 * ( (r_newrefdef.time * 0.77) - (int)(r_newrefdef.time * 0.77) )); + sadjust += 0x10000 * (-128 * ( (gpGlobals->time * 0.77) - (int)(gpGlobals->time * 0.77) )); } // PGM #endif @@ -1010,8 +1011,16 @@ void D_SolidSurf (surf_t *s) RI.currententity = gEngfuncs.GetEntityByIndex(0); //r_worldentity; pface = s->msurf; + + + if( !pface ) + return; #if 1 - miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip ); + + if( pface->flags & SURF_CONVEYOR ) + miplevel = 1; + else + miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip ); #else { float dot; @@ -1039,8 +1048,6 @@ void D_SolidSurf (surf_t *s) } #endif - if( !pface ) - return; // FIXME: make this passed in to D_CacheSurface pcurrentcache = D_CacheSurface (pface, miplevel); @@ -1125,7 +1132,7 @@ void D_DrawSurfaces (void) #if 1 if(s->flags & SURF_DRAWSKY) D_BackgroundSurf (s); - else if (s->flags & SURF_DRAWTURB) + else if (s->flags & SURF_DRAWTURB ) D_TurbulentSurf (s); else D_SolidSurf (s); diff --git a/r_main.c b/r_main.c index f606d33e..12fbf87b 100644 --- a/r_main.c +++ b/r_main.c @@ -1945,7 +1945,7 @@ qboolean R_Init() sw_mipscale = gEngfuncs.Cvar_Get ("sw_mipscale", "1", 0, ""); sw_reportedgeout = gEngfuncs.Cvar_Get ("sw_reportedgeout", "0", 0, ""); sw_reportsurfout = gEngfuncs.Cvar_Get ("sw_reportsurfout", "0", 0, ""); - sw_stipplealpha = gEngfuncs.Cvar_Get( "sw_stipplealpha", "0", FCVAR_ARCHIVE, "" ); + sw_stipplealpha = gEngfuncs.Cvar_Get( "sw_stipplealpha", "1", FCVAR_ARCHIVE, "" ); sw_surfcacheoverride = gEngfuncs.Cvar_Get ("sw_surfcacheoverride", "0", 0, ""); sw_waterwarp = gEngfuncs.Cvar_Get ("sw_waterwarp", "1", 0, ""); sw_mode = gEngfuncs.Cvar_Get( "sw_mode", "0", FCVAR_ARCHIVE, ""); diff --git a/r_poly.c b/r_poly.c index 129793bf..7237aaf4 100644 --- a/r_poly.c +++ b/r_poly.c @@ -252,8 +252,8 @@ void R_DrawSpanletTurbulentBlended66( void ) { pixel_t screen = *s_spanletvars.pdest; pixel_t src = btemp; - byte alpha = 4; - *s_spanletvars.pdest = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0x7f) >> 3 | ((src & 0xff)); + byte alpha = 5; + *s_spanletvars.pdest = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff)); } s_spanletvars.izi += s_spanletvars.izistep; @@ -281,8 +281,8 @@ void R_DrawSpanletTurbulentBlended33( void ) { pixel_t screen = *s_spanletvars.pdest; pixel_t src = btemp; - byte alpha = 4; - *s_spanletvars.pdest = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0x7f) >> 3 | ((src & 0xff)); + byte alpha = 2; + *s_spanletvars.pdest = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff)| ((src & 0xff)); } s_spanletvars.izi += s_spanletvars.izistep; @@ -316,8 +316,8 @@ void R_DrawSpanlet33( void ) { pixel_t screen = *s_spanletvars.pdest; pixel_t src = btemp; - byte alpha = 4; - *s_spanletvars.pdest = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0x7f) >> 3 | ((src & 0xff)); + byte alpha = 2; + *s_spanletvars.pdest = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff)| ((src & 0xff)); } } @@ -367,8 +367,8 @@ void R_DrawSpanlet66( void ) { pixel_t screen = *s_spanletvars.pdest; pixel_t src = btemp; - byte alpha = 4; - *s_spanletvars.pdest = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0x7f) >> 3 | ((src & 0xff)); + byte alpha = 5; + *s_spanletvars.pdest = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff)| ((src & 0xff)); } } diff --git a/r_surf.c b/r_surf.c index 65011ae1..37bd53f8 100644 --- a/r_surf.c +++ b/r_surf.c @@ -187,6 +187,14 @@ static void R_BuildLightMap( ) size = smax * tmax; + if( surf->flags & SURF_CONVEYOR ) + { + smax = ( info->lightextents[0] * 3 / sample_size ) + 1; + size = smax * tmax; + memset( blocklights, 0xff, sizeof( uint ) * size ); + return; + } + lm = surf->samples; memset( blocklights, 0, sizeof( uint ) * size ); @@ -1101,6 +1109,19 @@ surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) // r_drawsurf.image = R_GetTexture(R_TextureAnimation (surface)->gl_texturenum); + if( surface->flags & SURF_CONVEYOR ) + { + if( miplevel >= 1) + { + surface->extents[0] = surface->info->lightextents[0] * gEngfuncs.Mod_SampleSizeForFace( r_drawsurf.surf ) * 2 ; + surface->texturemins[0] = -surface->info->lightextents[0] * gEngfuncs.Mod_SampleSizeForFace( r_drawsurf.surf ); + } + else + { + surface->extents[0] = surface->info->lightextents[0] * gEngfuncs.Mod_SampleSizeForFace( r_drawsurf.surf ) ; + surface->texturemins[0] = -surface->info->lightextents[0] * gEngfuncs.Mod_SampleSizeForFace( r_drawsurf.surf )/2; + } + } /// todo: port this //r_drawsurf.lightadj[0] = r_newrefdef.lightstyles[surface->styles[0]].white*128; //r_drawsurf.lightadj[1] = r_newrefdef.lightstyles[surface->styles[1]].white*128; @@ -1138,6 +1159,7 @@ surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) r_drawsurf.surfwidth = surface->extents[0] >> miplevel; r_drawsurf.rowbytes = r_drawsurf.surfwidth; r_drawsurf.surfheight = surface->extents[1] >> miplevel; + // // allocate memory if needed From 29c216901255e6e7e2bc131872c5e736ccb5f951 Mon Sep 17 00:00:00 2001 From: mittorn Date: Fri, 29 Mar 2019 21:37:21 +0700 Subject: [PATCH 041/115] ref_soft: improve alpha map --- r_draw.c | 4 ++-- r_glblit.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- r_local.h | 4 +++- r_poly.c | 10 +++++----- r_surf.c | 2 +- 5 files changed, 57 insertions(+), 11 deletions(-) diff --git a/r_draw.c b/r_draw.c index bffd94b0..1e78e2a6 100644 --- a/r_draw.c +++ b/r_draw.c @@ -166,10 +166,10 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, pixel_t screen = dest[u]; dest[u] = vid.addmap[src & 0xff00|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 0); } - else if( alpha < 7) // && (vid.rendermode == kRenderTransAlpha || vid.rendermode == kRenderTransTexture ) ) + else if( alpha < 0) // && (vid.rendermode == kRenderTransAlpha || vid.rendermode == kRenderTransTexture ) ) { pixel_t screen = dest[u]; // | 0xff & screen & src ; - dest[u] = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) >> 3 | ((src & 0xff) >> 3); + dest[u] = BLEND_ALPHA( alpha, src, screen);//vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) >> 3 | ((src & 0xff) >> 3); } else diff --git a/r_glblit.c b/r_glblit.c index 20b33ca5..1e3a5ea1 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -159,7 +159,7 @@ void R_BuildBlendMaps() b = b1 * b2 / MASK(2); vid.modmap[index2|index1] = r << (2 + 3) | g << 2 | b; - +#if 0 for( a = 0; a < 8; a++ ) { r = r1 * (7 - a) / 7 + r2 * a / 7; @@ -168,7 +168,7 @@ void R_BuildBlendMaps() //if( b == 1 ) b = 0; vid.alphamap[a << 16|index2|index1] = r << (2 + 3) | g << 2 | b; } - +#endif } for( i = 0; i < 8192; i++ ) { @@ -201,6 +201,50 @@ void R_BuildBlendMaps() vid.colormap[index2|index1] = major << 8 | (minor & 0xFF); } } +#if 1 + for( i = 0; i < 1024; i++ ) + { + unsigned int r, g, b; + uint color = i << 6; + uint m = color >> 8; + uint j = color & 0xff; + + r1 = ((m >> (8 - 3) )<< 2 ) & MASK(5); + g1 = ((m >> (8 - 3 - 3)) << 3) & MASK(6); + b1 = ((m >> (8 - 3 - 3 - 2)) << 3) & MASK(5); + r1 |= MOVE_BIT(j, 5, 1) | MOVE_BIT(j, 2, 0); + g1 |= MOVE_BIT(j, 7, 2) | MOVE_BIT(j, 4, 1) | MOVE_BIT(j, 1, 0); + b1 |= MOVE_BIT(j, 6, 2) | MOVE_BIT(j, 3, 1) | MOVE_BIT(j, 0, 0); + + + unsigned short index1 = i; + FOR_EACH_COLOR(2) + { + unsigned int index2 = (r2 << (2 + 3) | g2 << 2 | b2) << 10; + unsigned int k; + for( k = 0; k < 3; k++ ) + { + unsigned int major, minor; + unsigned int a = k + 1; + + + r = r1 * (7 - a) / 7 + (r2 << 2) * a / 7; + g = g1 * (7 - a) / 7 + (g2 << 3) * a / 7; + b = b1 * (7 - a) / 7 + (b2 << 3) * a / 7; + + ASSERT( b < 32 ); + major = (((r >> 2) & MASK(3)) << 5) |( (( (g >> 3) & MASK(3)) << 2 ) )| (((b >> 3) & MASK(2))); + + // save minor GBRGBRGB + minor = MOVE_BIT(r,1,5) | MOVE_BIT(r,0,2) | MOVE_BIT(g,2,7) | MOVE_BIT(g,1,4) | MOVE_BIT(g,0,1) | MOVE_BIT(b,2,6)| MOVE_BIT(b,1,3)|MOVE_BIT(b,0,0); + minor = minor & ~0x3f; + + + vid.alphamap[k << 18|index2|index1] = major << 8 | (minor & 0xFF); + } + } + } +#endif } void R_AllocScreen(); diff --git a/r_local.h b/r_local.h index fe032ad7..52884b8c 100644 --- a/r_local.h +++ b/r_local.h @@ -144,7 +144,7 @@ typedef struct #endif byte addmap[256*256]; byte modmap[256*256]; - byte alphamap[8*256*256]; + pixel_t alphamap[3*1024*256]; pixel_t color; qboolean is2d; byte alpha; @@ -1349,6 +1349,8 @@ void R_ClipAndDrawPoly( float alpha, qboolean isturbulent, qboolean textured ); void R_SetUpWorldTransform (void); +#define BLEND_ALPHA_LOW(alpha, src, screen) (vid.alphamap[(alpha << 18) |( (src & 0xff00) << 2) | (screen >> 6)] | screen & 0x3f) +#define BLEND_ALPHA(alpha, src, dst) alpha > 3?BLEND_ALPHA_LOW(7 - 1 - alpha, dst,src):BLEND_ALPHA_LOW(alpha-1, src, dst) // // engine callbacks diff --git a/r_poly.c b/r_poly.c index 7237aaf4..2e300e9d 100644 --- a/r_poly.c +++ b/r_poly.c @@ -253,7 +253,7 @@ void R_DrawSpanletTurbulentBlended66( void ) pixel_t screen = *s_spanletvars.pdest; pixel_t src = btemp; byte alpha = 5; - *s_spanletvars.pdest = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff)); + *s_spanletvars.pdest = BLEND_ALPHA( alpha, src, screen);//vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff)); } s_spanletvars.izi += s_spanletvars.izistep; @@ -282,7 +282,7 @@ void R_DrawSpanletTurbulentBlended33( void ) pixel_t screen = *s_spanletvars.pdest; pixel_t src = btemp; byte alpha = 2; - *s_spanletvars.pdest = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff)| ((src & 0xff)); + *s_spanletvars.pdest = BLEND_ALPHA( alpha, src, screen); } s_spanletvars.izi += s_spanletvars.izistep; @@ -317,7 +317,7 @@ void R_DrawSpanlet33( void ) pixel_t screen = *s_spanletvars.pdest; pixel_t src = btemp; byte alpha = 2; - *s_spanletvars.pdest = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff)| ((src & 0xff)); + *s_spanletvars.pdest = BLEND_ALPHA( alpha, src, screen); } } @@ -336,7 +336,7 @@ void R_DrawSpanletConstant33( void ) { if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16)) { - *s_spanletvars.pdest = vid.alphamap[r_polyblendcolor+*s_spanletvars.pdest*256]; + //*s_spanletvars.pdest = BLEND_ALPHA( alpha, src, screen); } s_spanletvars.izi += s_spanletvars.izistep; @@ -368,7 +368,7 @@ void R_DrawSpanlet66( void ) pixel_t screen = *s_spanletvars.pdest; pixel_t src = btemp; byte alpha = 5; - *s_spanletvars.pdest = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff)| ((src & 0xff)); + *s_spanletvars.pdest = BLEND_ALPHA( alpha, src, screen); } } diff --git a/r_surf.c b/r_surf.c index 37bd53f8..85c869c3 100644 --- a/r_surf.c +++ b/r_surf.c @@ -1081,7 +1081,7 @@ void R_DrawSurfaceDecals() pixel_t screen = dest[u]; // | 0xff & screen & src ; if( screen == TRANSPARENT_COLOR ) continue; - dest[u] = vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0x7f) >> 3 | ((src & 0xff)); + dest[u] = BLEND_ALPHA( alpha, src, screen); } else From 9b158f592692d0f12ccf52e9cca2b4166abad5ae Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 30 Mar 2019 01:34:57 +0700 Subject: [PATCH 042/115] ref_soft: Studio alpha blending --- r_draw.c | 2 +- r_main.c | 5 ++++- r_poly.c | 28 ++++++++++++++-------------- r_polyse.c | 28 ++++++++++++++++------------ 4 files changed, 35 insertions(+), 28 deletions(-) diff --git a/r_draw.c b/r_draw.c index 1e78e2a6..cd6aa659 100644 --- a/r_draw.c +++ b/r_draw.c @@ -166,7 +166,7 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, pixel_t screen = dest[u]; dest[u] = vid.addmap[src & 0xff00|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 0); } - else if( alpha < 0) // && (vid.rendermode == kRenderTransAlpha || vid.rendermode == kRenderTransTexture ) ) + else if( alpha < 7) // && (vid.rendermode == kRenderTransAlpha || vid.rendermode == kRenderTransTexture ) ) { pixel_t screen = dest[u]; // | 0xff & screen & src ; dest[u] = BLEND_ALPHA( alpha, src, screen);//vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) >> 3 | ((src & 0xff) >> 3); diff --git a/r_main.c b/r_main.c index 12fbf87b..e95c849d 100644 --- a/r_main.c +++ b/r_main.c @@ -1023,6 +1023,8 @@ void R_DrawEntitiesOnList( void ) //RI.currententity = gEngfuncs.GetEntityByIndex(0); extern void (*d_pdrawspans)(void *); extern void R_PolysetFillSpans8 ( void * ); + extern void R_PolysetDrawSpansConstant8_33( void *pspanpackage); + extern void R_PolysetDrawSpans8_33( void *pspanpackage); d_pdrawspans = R_PolysetFillSpans8; // first draw solid entities for( i = 0; i < tr.draw_list->num_solid_entities && !RI.onlyClientDraw; i++ ) @@ -1109,7 +1111,7 @@ void R_DrawEntitiesOnList( void ) gEngfuncs.pfnDrawNormalTriangles(); // GL_CheckForErrors(); - + d_pdrawspans = R_PolysetDrawSpans8_33; // then draw translucent entities for( i = 0; i < tr.draw_list->num_trans_entities && !RI.onlyClientDraw; i++ ) { @@ -1166,6 +1168,7 @@ void R_DrawEntitiesOnList( void ) //GL_CheckForErrors(); // pglDisable( GL_BLEND ); // Trinity Render issues + d_pdrawspans = R_PolysetFillSpans8; R_SetUpWorldTransform(); if( !RI.onlyClientDraw ) diff --git a/r_poly.c b/r_poly.c index 2e300e9d..fe03d18e 100644 --- a/r_poly.c +++ b/r_poly.c @@ -62,7 +62,7 @@ static void R_DrawPoly( qboolean iswater ); */ void R_DrawSpanletOpaque( void ) { - unsigned btemp; + pixel_t btemp; do { @@ -94,7 +94,7 @@ void R_DrawSpanletOpaque( void ) */ void R_DrawSpanletTurbulentStipple33( void ) { - unsigned btemp; + pixel_t btemp; int sturb, tturb; pixel_t *pdest = s_spanletvars.pdest; short *pz = s_spanletvars.pz; @@ -151,7 +151,7 @@ void R_DrawSpanletTurbulentStipple33( void ) */ void R_DrawSpanletTurbulentStipple66( void ) { - unsigned btemp; + pixel_t btemp; int sturb, tturb; pixel_t *pdest = s_spanletvars.pdest; short *pz = s_spanletvars.pz; @@ -238,7 +238,7 @@ void R_DrawSpanletTurbulentStipple66( void ) */ void R_DrawSpanletTurbulentBlended66( void ) { - unsigned btemp; + pixel_t btemp; int sturb, tturb; do @@ -267,7 +267,7 @@ void R_DrawSpanletTurbulentBlended66( void ) void R_DrawSpanletTurbulentBlended33( void ) { - unsigned btemp; + pixel_t btemp; int sturb, tturb; do @@ -299,7 +299,7 @@ void R_DrawSpanletTurbulentBlended33( void ) */ void R_DrawSpanlet33( void ) { - unsigned btemp; + pixel_t btemp; do { @@ -310,7 +310,7 @@ void R_DrawSpanlet33( void ) btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth); - if ( btemp != 255 ) + if ( btemp != TRANSPARENT_COLOR ) { if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16)) { @@ -350,7 +350,7 @@ void R_DrawSpanletConstant33( void ) */ void R_DrawSpanlet66( void ) { - unsigned btemp; + pixel_t btemp; do { @@ -361,7 +361,7 @@ void R_DrawSpanlet66( void ) btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth); - if ( btemp != 255 ) + if ( btemp != TRANSPARENT_COLOR ) { if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16)) { @@ -386,7 +386,7 @@ void R_DrawSpanlet66( void ) */ void R_DrawSpanlet33Stipple( void ) { - unsigned btemp; + pixel_t btemp; pixel_t *pdest = s_spanletvars.pdest; short *pz = s_spanletvars.pz; int izi = s_spanletvars.izi; @@ -422,7 +422,7 @@ void R_DrawSpanlet33Stipple( void ) btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) ); - if ( btemp != 255 ) + if ( btemp != TRANSPARENT_COLOR ) { if ( *pz <= ( izi >> 16 ) ) *pdest = btemp; @@ -445,7 +445,7 @@ void R_DrawSpanlet33Stipple( void ) */ void R_DrawSpanlet66Stipple( void ) { - unsigned btemp; + pixel_t btemp; pixel_t *pdest = s_spanletvars.pdest; short *pz = s_spanletvars.pz; int izi = s_spanletvars.izi; @@ -481,7 +481,7 @@ void R_DrawSpanlet66Stipple( void ) btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) ); - if ( btemp != 255 ) + if ( btemp != TRANSPARENT_COLOR ) { if ( *pz <= ( izi >> 16 ) ) *pdest = btemp; @@ -506,7 +506,7 @@ void R_DrawSpanlet66Stipple( void ) btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) ); - if ( btemp != 255 ) + if ( btemp != TRANSPARENT_COLOR ) { if ( *pz <= ( izi >> 16 ) ) *pdest = btemp; diff --git a/r_polyse.c b/r_polyse.c index c8de02fd..71700472 100644 --- a/r_polyse.c +++ b/r_polyse.c @@ -820,8 +820,8 @@ R_PolysetDrawSpans8 void R_PolysetDrawSpans8_33( spanpackage_t *pspanpackage) { int lcount; - byte *lpdest; - byte *lptex; + pixel_t *lpdest; + pixel_t *lptex; int lsfrac, ltfrac; int llight; int lzi; @@ -856,9 +856,13 @@ void R_PolysetDrawSpans8_33( spanpackage_t *pspanpackage) { if ((lzi >> 16) >= *lpz) { - int temp = vid.colormap[*lptex + ( llight & 0xFF00 )]; + pixel_t temp = *lptex;//vid.colormap[*lptex + ( llight & 0xFF00 )]; - *lpdest = vid.alphamap[temp+ *lpdest*256]; + int alpha = tr.blend * 7; + if( alpha == 7 ) + *lpdest = temp; + else if(alpha) + *lpdest = BLEND_ALPHA(alpha,temp,*lpdest);//vid.alphamap[temp+ *lpdest*256]; } lpdest++; lzi += r_zistepx; @@ -884,7 +888,7 @@ void R_PolysetDrawSpans8_33( spanpackage_t *pspanpackage) void R_PolysetDrawSpansConstant8_33( spanpackage_t *pspanpackage) { int lcount; - byte *lpdest; + pixel_t *lpdest; int lzi; short *lpz; @@ -913,7 +917,7 @@ void R_PolysetDrawSpansConstant8_33( spanpackage_t *pspanpackage) { if ((lzi >> 16) >= *lpz) { - *lpdest = vid.alphamap[r_aliasblendcolor + *lpdest*256]; + *lpdest = BLEND_ALPHA(2,r_aliasblendcolor,*lpdest);//vid.alphamap[r_aliasblendcolor + *lpdest*256]; } lpdest++; lzi += r_zistepx; @@ -928,8 +932,8 @@ void R_PolysetDrawSpansConstant8_33( spanpackage_t *pspanpackage) void R_PolysetDrawSpans8_66(spanpackage_t *pspanpackage) { int lcount; - byte *lpdest; - byte *lptex; + pixel_t *lpdest; + pixel_t *lptex; int lsfrac, ltfrac; int llight; int lzi; @@ -966,7 +970,7 @@ void R_PolysetDrawSpans8_66(spanpackage_t *pspanpackage) { int temp = vid.colormap[*lptex + ( llight & 0xFF00 )]; - *lpdest = vid.alphamap[temp*256 + *lpdest]; + *lpdest = BLEND_ALPHA(5,temp,*lpdest);//vid.alphamap[temp*256 + *lpdest]; *lpz = lzi >> 16; } lpdest++; @@ -993,7 +997,7 @@ void R_PolysetDrawSpans8_66(spanpackage_t *pspanpackage) void R_PolysetDrawSpansConstant8_66( spanpackage_t *pspanpackage) { int lcount; - byte *lpdest; + pixel_t *lpdest; int lzi; short *lpz; @@ -1022,7 +1026,7 @@ void R_PolysetDrawSpansConstant8_66( spanpackage_t *pspanpackage) { if ((lzi >> 16) >= *lpz) { - *lpdest = vid.alphamap[r_aliasblendcolor*256 + *lpdest]; + *lpdest = BLEND_ALPHA(5,r_aliasblendcolor,*lpdest);//vid.alphamap[r_aliasblendcolor*256 + *lpdest]; } lpdest++; lzi += r_zistepx; @@ -1219,7 +1223,7 @@ void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) } while (--lcount); } - pspanpackage++; + pspanpackage ++; } while (pspanpackage->count != -999999); } #endif From 95ff7690201cecf1ca23fbf5549a1804815a70bc Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 30 Mar 2019 02:40:46 +0700 Subject: [PATCH 043/115] ref_soft: Add option to disable slow brush transparency --- r_image.c | 2 +- r_local.h | 4 ++++ r_main.c | 18 +++++++++++++++--- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/r_image.c b/r_image.c index 6a73e7e4..44cb659b 100644 --- a/r_image.c +++ b/r_image.c @@ -559,7 +559,7 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) { unsigned int alpha = (pic->buffer[i * 4 + 3] * 8 / 256) << (16 - 3); tex->alpha_pixels[i] = (tex->pixels[j][i] >> 3) | alpha; - if( pic->buffer[i * 4 + 3] < 128 && FBitSet( pic->flags, IMAGE_ONEBIT_ALPHA ) ) + if( !sw_noalphabrushes->value && pic->buffer[i * 4 + 3] < 128 && FBitSet( pic->flags, IMAGE_ONEBIT_ALPHA ) ) tex->pixels[j][i] = TRANSPARENT_COLOR; //0000 0011 0100 1001; } diff --git a/r_local.h b/r_local.h index 52884b8c..ff44543b 100644 --- a/r_local.h +++ b/r_local.h @@ -1227,6 +1227,10 @@ extern cvar_t *sw_waterwarp; extern cvar_t *sw_texfilt; extern cvar_t *r_decals; +extern cvar_t *sw_notransbrushes; +extern cvar_t *sw_noalphabrushes; + + extern vec3_t modelorg; extern vec3_t r_origin; diff --git a/r_main.c b/r_main.c index e95c849d..13b1deef 100644 --- a/r_main.c +++ b/r_main.c @@ -77,13 +77,14 @@ cvar_t *sw_drawflat; cvar_t *sw_draworder; cvar_t *sw_maxedges; cvar_t *sw_maxsurfs; -cvar_t *sw_mode; cvar_t *sw_reportedgeout; cvar_t *sw_reportsurfout; cvar_t *sw_stipplealpha; cvar_t *sw_surfcacheoverride; cvar_t *sw_waterwarp; cvar_t *sw_texfilt; +cvar_t *sw_notransbrushes; +cvar_t *sw_noalphabrushes; cvar_t *r_drawworld; cvar_t *r_drawentities; @@ -246,8 +247,17 @@ Opaque entity can be brush or studio model but sprite */ static qboolean R_OpaqueEntity( cl_entity_t *ent ) { - if( R_GetEntityRenderMode( ent ) == kRenderNormal ) + int rendermode = R_GetEntityRenderMode( ent ); + + if( rendermode == kRenderNormal ) + return true; + + if( sw_notransbrushes->value && ent->model && ent->model->type == mod_brush && rendermode == kRenderTransTexture ) return true; + + if( sw_noalphabrushes->value && ent->model && ent->model->type == mod_brush && rendermode == kRenderTransAlpha ) + return true; + return false; } @@ -1951,7 +1961,9 @@ qboolean R_Init() sw_stipplealpha = gEngfuncs.Cvar_Get( "sw_stipplealpha", "1", FCVAR_ARCHIVE, "" ); sw_surfcacheoverride = gEngfuncs.Cvar_Get ("sw_surfcacheoverride", "0", 0, ""); sw_waterwarp = gEngfuncs.Cvar_Get ("sw_waterwarp", "1", 0, ""); - sw_mode = gEngfuncs.Cvar_Get( "sw_mode", "0", FCVAR_ARCHIVE, ""); + sw_notransbrushes = gEngfuncs.Cvar_Get( "sw_notransbrushes", "0", FCVAR_ARCHIVE, "do not apply transparency to water/glasses (faster)"); + sw_noalphabrushes = gEngfuncs.Cvar_Get( "sw_noalphabrushes", "0", FCVAR_ARCHIVE, "do not draw brush holes (faster)"); + sw_texfilt = gEngfuncs.Cvar_Get ("sw_texfilt", "0", 0, "texture dither"); //r_lefthand = ri.Cvar_Get( "hand", "0", FCVAR_USERINFO | FCVAR_ARCHIVE ); // r_speeds = ri.Cvar_Get ("r_speeds", "0", 0); From b0ed8a5ba360e0a63b1b21a12586249c8375e496 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 30 Mar 2019 04:50:18 +0700 Subject: [PATCH 044/115] ref_soft: Fix some UB --- r_decals.c | 2 ++ r_image.c | 6 ++++-- r_local.h | 13 ++++++++++--- r_polyse.c | 24 +++++++++++++++++++++++- r_surf.c | 12 +++++++++++- r_triapi.c | 4 ++-- 6 files changed, 52 insertions(+), 9 deletions(-) diff --git a/r_decals.c b/r_decals.c index f3fd318d..9bca9e18 100644 --- a/r_decals.c +++ b/r_decals.c @@ -1173,6 +1173,8 @@ int R_CreateDecalList( decallist_t *pList ) int total = 0; int i, depth; + return 0; // crash on changelevel. API bug? + if( WORLDMODEL ) { for( i = 0; i < MAX_RENDER_DECALS; i++ ) diff --git a/r_image.c b/r_image.c index 44cb659b..e72903fb 100644 --- a/r_image.c +++ b/r_image.c @@ -531,9 +531,11 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) texsize = GL_CalcTextureSize( width, height, tex->depth ); size = GL_CalcImageSize( pic->type, width, height, tex->depth ); //GL_TextureImageRAW( tex, i, j, width, height, tex->depth, pic->type, data ); - tex->pixels[j] = Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 64 ); + // increase size to workaround triangle renderer bugs + // it seems to assume memory readable. maybe it was pointed to WAD? + tex->pixels[j] = (byte*)Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 256 ) + 128; if( j == 0 && tex->flags & TF_HAS_ALPHA ) - tex->alpha_pixels = Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 64 ); + tex->alpha_pixels = (byte*)Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 256 ) + 128; for(i = 0; i < height * width; i++ ) { diff --git a/r_local.h b/r_local.h index ff44543b..6f843611 100644 --- a/r_local.h +++ b/r_local.h @@ -1218,7 +1218,6 @@ extern cvar_t *sw_maxedges; extern cvar_t *sw_maxsurfs; extern cvar_t *sw_mipcap; extern cvar_t *sw_mipscale; -extern cvar_t *sw_mode; extern cvar_t *sw_reportsurfout; extern cvar_t *sw_reportedgeout; extern cvar_t *sw_stipplealpha; @@ -1360,7 +1359,7 @@ void R_SetUpWorldTransform (void); // engine callbacks // #include "crtlib.h" - +#if 1 #define Mem_Malloc( pool, size ) gEngfuncs._Mem_Alloc( pool, size, false, __FILE__, __LINE__ ) #define Mem_Calloc( pool, size ) gEngfuncs._Mem_Alloc( pool, size, true, __FILE__, __LINE__ ) #define Mem_Realloc( pool, ptr, size ) gEngfuncs._Mem_Realloc( pool, ptr, size, true, __FILE__, __LINE__ ) @@ -1368,5 +1367,13 @@ void R_SetUpWorldTransform (void); #define Mem_AllocPool( name ) gEngfuncs._Mem_AllocPool( name, __FILE__, __LINE__ ) #define Mem_FreePool( pool ) gEngfuncs._Mem_FreePool( pool, __FILE__, __LINE__ ) #define Mem_EmptyPool( pool ) gEngfuncs._Mem_EmptyPool( pool, __FILE__, __LINE__ ) - +#else +#define Mem_Malloc( pool, size ) malloc(size) +#define Mem_Calloc( pool, size ) calloc(1,size) +#define Mem_Realloc( pool, ptr, size ) realloc(ptr, size) +#define Mem_Free( mem ) free(mem) +#define Mem_AllocPool( name ) gEngfuncs._Mem_AllocPool( name, __FILE__, __LINE__ ) +#define Mem_FreePool( pool ) gEngfuncs._Mem_FreePool( pool, __FILE__, __LINE__ ) +#define Mem_EmptyPool( pool ) gEngfuncs._Mem_EmptyPool( pool, __FILE__, __LINE__ ) +#endif #endif // GL_LOCAL_H diff --git a/r_polyse.c b/r_polyse.c index 71700472..6a2abe24 100644 --- a/r_polyse.c +++ b/r_polyse.c @@ -40,7 +40,7 @@ typedef struct { void *pdest; short *pz; int count; - byte *ptex; + pixel_t *ptex; int sfrac, tfrac, light, zi; } spanpackage_t; @@ -279,6 +279,9 @@ void R_PolysetScanLeftEdge_C(int height) d_pedgespanpackage->light = d_light; d_pedgespanpackage->zi = d_zi; + if( d_pedgespanpackage->ptex - (pixel_t*)r_affinetridesc.pskin < 0 ) + d_pedgespanpackage->ptex = r_affinetridesc.pskin; + d_pedgespanpackage++; errorterm += erroradjustup; @@ -291,6 +294,7 @@ void R_PolysetScanLeftEdge_C(int height) d_sfrac += d_sfracextrastep; d_ptex += d_sfrac >> 16; + d_sfrac &= 0xFFFF; d_tfrac += d_tfracextrastep; if (d_tfrac & 0x10000) @@ -856,6 +860,13 @@ void R_PolysetDrawSpans8_33( spanpackage_t *pspanpackage) { if ((lzi >> 16) >= *lpz) { +#if 0 + if((int)(lptex - (pixel_t*)r_affinetridesc.pskin) > r_affinetridesc.skinwidth * r_affinetridesc.skinheight || (int)(lptex - (pixel_t*)r_affinetridesc.pskin) < 0 ) + { + printf("%d %d %d %d\n",(int)(lptex - (pixel_t*)r_affinetridesc.pskin), r_affinetridesc.skinwidth * r_affinetridesc.skinheight, lsfrac, a_ststepxwhole ); + return; + } +#endif pixel_t temp = *lptex;//vid.colormap[*lptex + ( llight & 0xFF00 )]; int alpha = tr.blend * 7; @@ -1196,6 +1207,13 @@ void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) *lpdest = ((byte *)vid.colormap)[irtable[*lptex]]; else*/ //*lpdest = *lptex; //((byte *)vid.colormap)[*lptex + (llight & 0xFF00)]; +#if 0 // check for texture bounds to make asan happy + if((int)(lptex - (pixel_t*)r_affinetridesc.pskin) > r_affinetridesc.skinwidth * r_affinetridesc.skinheight || (int)(lptex - (pixel_t*)r_affinetridesc.pskin) < 0 ) + { + printf("%d %d %d %d\n",(int)(lptex - (pixel_t*)r_affinetridesc.pskin), r_affinetridesc.skinwidth * r_affinetridesc.skinheight, lsfrac, a_ststepxwhole ); + return; + } +#endif pixel_t src = *lptex; //*lpdest = //vid.colormap[src & 0xff00|(llight>>8)] << 8 | (src & llight & 0xff) | ((src & 0xff) >> 3); // very dirty, maybe need dual colormap? @@ -1301,6 +1319,8 @@ void R_RasterizeAliasPolySmooth (void) // FIXME: need to clamp l, s, t, at both ends? d_pedgespanpackage->light = d_light; d_pedgespanpackage->zi = d_zi; + if( d_pedgespanpackage->ptex - (pixel_t*)r_affinetridesc.pskin < 0 ) + d_pedgespanpackage->ptex = r_affinetridesc.pskin; d_pedgespanpackage++; } @@ -1432,6 +1452,8 @@ void R_RasterizeAliasPolySmooth (void) // FIXME: need to clamp l, s, t, at both ends? d_pedgespanpackage->light = d_light; d_pedgespanpackage->zi = d_zi; + if( d_pedgespanpackage->ptex - (pixel_t*)r_affinetridesc.pskin < 0 ) + d_pedgespanpackage->ptex = r_affinetridesc.pskin; d_pedgespanpackage++; } diff --git a/r_surf.c b/r_surf.c index 85c869c3..0907fe34 100644 --- a/r_surf.c +++ b/r_surf.c @@ -1026,6 +1026,16 @@ void R_DrawSurfaceDecals() h = r_drawsurf.surfheight - y; } + if( s1 < 0 ) + s1 = 0; + if( t1 < 0 ) + t1 = 0; + + if( s2 > tex->width ) + s2 = tex->width; + if( t2 > tex->height ) + t2 = tex->height; + if( !tex->pixels[0] || s1 >= s2 || t1 >= t2 ) continue; @@ -1057,7 +1067,7 @@ void R_DrawSurfaceDecals() { f = 0; - fstep = s2*0x10000/w; + fstep = (s2-s1)*0x10000/w; if( w == s2 - s1 ) fstep = 0x10000; diff --git a/r_triapi.c b/r_triapi.c index 922fbe54..e6c3193b 100644 --- a/r_triapi.c +++ b/r_triapi.c @@ -218,8 +218,8 @@ TriTexCoord2f void TriTexCoord2f( float u, float v ) { //pglTexCoord2f( u, v ); - s = r_affinetridesc.skinwidth * u; - t = r_affinetridesc.skinheight * v; + s = r_affinetridesc.skinwidth * bound(0,u,1); + t = r_affinetridesc.skinheight * bound(0,v,1); } /* From f34db629408956ade0f7dda77f434092df78ead2 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 30 Mar 2019 20:24:58 +0700 Subject: [PATCH 045/115] ref_soft: Add sprite, EFX --- r_beams.c | 1313 +++++++++++++++++++++++++++++++++++++++++++++++++++ r_context.c | 41 +- r_draw.c | 10 +- r_image.c | 4 +- r_local.h | 17 +- r_main.c | 21 +- r_part.c | 300 ++++++++++++ r_sprite.c | 1087 ++++++++++++++++++++++++++++++++++++++++++ r_triapi.c | 15 +- 9 files changed, 2753 insertions(+), 55 deletions(-) create mode 100644 r_beams.c create mode 100644 r_part.c create mode 100644 r_sprite.c diff --git a/r_beams.c b/r_beams.c new file mode 100644 index 00000000..759b751a --- /dev/null +++ b/r_beams.c @@ -0,0 +1,1313 @@ +/* +gl_beams.c - beams rendering +Copyright (C) 2009 Uncle Mike + +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 3 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. +*/ + +#include "r_local.h" +#include "r_efx.h" +#include "event_flags.h" +#include "entity_types.h" +#include "triangleapi.h" +#include "customentity.h" +#include "cl_tent.h" +#include "pm_local.h" + +#include "studio.h" + +#define NOISE_DIVISIONS 64 // don't touch - many tripmines cause the crash when it equal 128 + +typedef struct +{ + vec3_t pos; + float texcoord; // Y texture coordinate + float width; +} beamseg_t; + +/* +============================================================== + +FRACTAL NOISE + +============================================================== +*/ +static float rgNoise[NOISE_DIVISIONS+1]; // global noise array + +// freq2 += step * 0.1; +// Fractal noise generator, power of 2 wavelength +static void FracNoise( float *noise, int divs ) +{ + int div2; + + div2 = divs >> 1; + if( divs < 2 ) return; + + // noise is normalized to +/- scale + noise[div2] = ( noise[0] + noise[divs] ) * 0.5f + divs * gEngfuncs.COM_RandomFloat( -0.125f, 0.125f ); + + if( div2 > 1 ) + { + FracNoise( &noise[div2], div2 ); + FracNoise( noise, div2 ); + } +} + +static void SineNoise( float *noise, int divs ) +{ + float freq = 0; + float step = M_PI / (float)divs; + int i; + + for( i = 0; i < divs; i++ ) + { + noise[i] = sin( freq ); + freq += step; + } +} + + +/* +============================================================== + +BEAM MATHLIB + +============================================================== +*/ +static void R_BeamComputePerpendicular( const vec3_t vecBeamDelta, vec3_t pPerp ) +{ + // direction in worldspace of the center of the beam + vec3_t vecBeamCenter; + + VectorNormalize2( vecBeamDelta, vecBeamCenter ); + CrossProduct( RI.vforward, vecBeamCenter, pPerp ); + VectorNormalize( pPerp ); +} + +static void R_BeamComputeNormal( const vec3_t vStartPos, const vec3_t vNextPos, vec3_t pNormal ) +{ + // vTangentY = line vector for beam + vec3_t vTangentY, vDirToBeam; + + VectorSubtract( vStartPos, vNextPos, vTangentY ); + + // vDirToBeam = vector from viewer origin to beam + VectorSubtract( vStartPos, RI.vieworg, vDirToBeam ); + + // get a vector that is perpendicular to us and perpendicular to the beam. + // this is used to fatten the beam. + CrossProduct( vTangentY, vDirToBeam, pNormal ); + VectorNormalizeFast( pNormal ); +} + + +/* +============== +R_BeamCull + +Cull the beam by bbox +============== +*/ +qboolean R_BeamCull( const vec3_t start, const vec3_t end, qboolean pvsOnly ) +{ + vec3_t mins, maxs; + int i; + return false; +/* + for( i = 0; i < 3; i++ ) + { + if( start[i] < end[i] ) + { + mins[i] = start[i]; + maxs[i] = end[i]; + } + else + { + mins[i] = end[i]; + maxs[i] = start[i]; + } + + // don't let it be zero sized + if( mins[i] == maxs[i] ) + maxs[i] += 1.0f; + } + + // check bbox + if( gEngfuncs.Mod_BoxVisible( mins, maxs, Mod_GetCurrentVis( ))) + { + if( pvsOnly || !R_CullBox( mins, maxs )) + { + // beam is visible + return false; + } + } + + // beam is culled + return true; + */ +} + +/* +================ +CL_AddCustomBeam + +Add the beam that encoded as custom entity +================ +*/ +void CL_AddCustomBeam( cl_entity_t *pEnvBeam ) +{ + if( tr.draw_list->num_beam_entities >= MAX_VISIBLE_PACKET ) + { + gEngfuncs.Con_Printf( S_ERROR "Too many beams %d!\n", tr.draw_list->num_beam_entities ); + return; + } + + if( pEnvBeam ) + { + tr.draw_list->beam_entities[tr.draw_list->num_beam_entities] = pEnvBeam; + tr.draw_list->num_beam_entities++; + } +} + + +/* +============================================================== + +BEAM DRAW METHODS + +============================================================== +*/ +/* +================ +R_DrawSegs + +general code for drawing beams +================ +*/ +static void R_DrawSegs( vec3_t source, vec3_t delta, float width, float scale, float freq, float speed, int segments, int flags ) +{ + int noiseIndex, noiseStep; + int i, total_segs, segs_drawn; + float div, length, fraction, factor; + float flMaxWidth, vLast, vStep, brightness; + vec3_t perp1, vLastNormal; + beamseg_t curSeg; + + if( segments < 2 ) return; + + length = VectorLength( delta ); + flMaxWidth = width * 0.5f; + div = 1.0f / ( segments - 1 ); + + if( length * div < flMaxWidth * 1.414f ) + { + // here, we have too many segments; we could get overlap... so lets have less segments + segments = (int)( length / ( flMaxWidth * 1.414f )) + 1.0f; + if( segments < 2 ) segments = 2; + } + + if( segments > NOISE_DIVISIONS ) + segments = NOISE_DIVISIONS; + + div = 1.0f / (segments - 1); + length *= 0.01f; + vStep = length * div; // Texture length texels per space pixel + + // Scroll speed 3.5 -- initial texture position, scrolls 3.5/sec (1.0 is entire texture) + vLast = fmod( freq * speed, 1 ); + + if( flags & FBEAM_SINENOISE ) + { + if( segments < 16 ) + { + segments = 16; + div = 1.0f / ( segments - 1 ); + } + scale *= 100.0f; + length = segments * 0.1f; + } + else + { + scale *= length * 2.0; + } + + // Iterator to resample noise waveform (it needs to be generated in powers of 2) + noiseStep = (int)((float)( NOISE_DIVISIONS - 1 ) * div * 65536.0f ); + brightness = 1.0f; + noiseIndex = 0; + + if( FBitSet( flags, FBEAM_SHADEIN )) + brightness = 0; + + // Choose two vectors that are perpendicular to the beam + R_BeamComputePerpendicular( delta, perp1 ); + + total_segs = segments; + segs_drawn = 0; + + // specify all the segments. + for( i = 0; i < segments; i++ ) + { + beamseg_t nextSeg; + vec3_t vPoint1, vPoint2; + + Assert( noiseIndex < ( NOISE_DIVISIONS << 16 )); + + fraction = i * div; + + VectorMA( source, fraction, delta, nextSeg.pos ); + + // distort using noise + if( scale != 0 ) + { + factor = rgNoise[noiseIndex>>16] * scale; + + if( FBitSet( flags, FBEAM_SINENOISE )) + { + float s, c; + + SinCos( fraction * M_PI * length + freq, &s, &c ); + VectorMA( nextSeg.pos, (factor * s), RI.vup, nextSeg.pos ); + + // rotate the noise along the perpendicluar axis a bit to keep the bolt from looking diagonal + VectorMA( nextSeg.pos, (factor * c), RI.vright, nextSeg.pos ); + } + else + { + VectorMA( nextSeg.pos, factor, perp1, nextSeg.pos ); + } + } + + // specify the next segment. + nextSeg.width = width * 2.0f; + nextSeg.texcoord = vLast; + + if( segs_drawn > 0 ) + { + // Get a vector that is perpendicular to us and perpendicular to the beam. + // This is used to fatten the beam. + vec3_t vNormal, vAveNormal; + + R_BeamComputeNormal( curSeg.pos, nextSeg.pos, vNormal ); + + if( segs_drawn > 1 ) + { + // Average this with the previous normal + VectorAdd( vNormal, vLastNormal, vAveNormal ); + VectorScale( vAveNormal, 0.5f, vAveNormal ); + VectorNormalizeFast( vAveNormal ); + } + else + { + VectorCopy( vNormal, vAveNormal ); + } + + VectorCopy( vNormal, vLastNormal ); + + // draw regular segment + VectorMA( curSeg.pos, ( curSeg.width * 0.5f ), vAveNormal, vPoint1 ); + VectorMA( curSeg.pos, (-curSeg.width * 0.5f ), vAveNormal, vPoint2 ); + + TriTexCoord2f( 0.0f, curSeg.texcoord ); + TriBrightness( brightness ); + //pglNormal3fv( vAveNormal ); + TriVertex3fv( vPoint1 ); + + TriTexCoord2f( 1.0f, curSeg.texcoord ); + TriBrightness( brightness ); + //pflNormal3fv( vAveNormal ); + TriVertex3fv( vPoint2 ); + } + + curSeg = nextSeg; + segs_drawn++; + + if( FBitSet( flags, FBEAM_SHADEIN ) && FBitSet( flags, FBEAM_SHADEOUT )) + { + if( fraction < 0.5f ) brightness = fraction; + else brightness = ( 1.0f - fraction ); + } + else if( FBitSet( flags, FBEAM_SHADEIN )) + { + brightness = fraction; + } + else if( FBitSet( flags, FBEAM_SHADEOUT )) + { + brightness = 1.0f - fraction; + } + + if( segs_drawn == total_segs ) + { + // draw the last segment + VectorMA( curSeg.pos, ( curSeg.width * 0.5f ), vLastNormal, vPoint1 ); + VectorMA( curSeg.pos, (-curSeg.width * 0.5f ), vLastNormal, vPoint2 ); + + // specify the points. + TriTexCoord2f( 0.0f, curSeg.texcoord ); + TriBrightness( brightness ); + //pglNormal3fv( vLastNormal ); + TriVertex3fv( vPoint1 ); + + TriTexCoord2f( 1.0f, curSeg.texcoord ); + TriBrightness( brightness ); + //pglNormal3fv( vLastNormal ); + TriVertex3fv( vPoint2 ); + } + + vLast += vStep; // Advance texture scroll (v axis only) + noiseIndex += noiseStep; + } +} + +/* +================ +R_DrawTorus + +Draw beamtours +================ +*/ +void R_DrawTorus( vec3_t source, vec3_t delta, float width, float scale, float freq, float speed, int segments ) +{ + int i, noiseIndex, noiseStep; + float div, length, fraction, factor, vLast, vStep; + vec3_t last1, last2, point, screen, screenLast, tmp, normal; + + if( segments < 2 ) + return; + + if( segments > NOISE_DIVISIONS ) + segments = NOISE_DIVISIONS; + + length = VectorLength( delta ) * 0.01; + if( length < 0.5 ) length = 0.5; // don't lose all of the noise/texture on short beams + + div = 1.0f / (segments - 1); + + vStep = length * div; // Texture length texels per space pixel + + // Scroll speed 3.5 -- initial texture position, scrolls 3.5/sec (1.0 is entire texture) + vLast = fmod( freq * speed, 1 ); + scale = scale * length; + + // Iterator to resample noise waveform (it needs to be generated in powers of 2) + noiseStep = (int)((float)( NOISE_DIVISIONS - 1 ) * div * 65536.0f ); + noiseIndex = 0; + + for( i = 0; i < segments; i++ ) + { + float s, c; + + fraction = i * div; + SinCos( fraction * M_PI2, &s, &c ); + + point[0] = s * freq * delta[2] + source[0]; + point[1] = c * freq * delta[2] + source[1]; + point[2] = source[2]; + + // distort using noise + if( scale != 0 ) + { + if(( noiseIndex >> 16 ) < NOISE_DIVISIONS ) + { + factor = rgNoise[noiseIndex>>16] * scale; + VectorMA( point, factor, RI.vup, point ); + + // rotate the noise along the perpendicluar axis a bit to keep the bolt from looking diagonal + factor = rgNoise[noiseIndex>>16] * scale * cos( fraction * M_PI * 3 + freq ); + VectorMA( point, factor, RI.vright, point ); + } + } + + // Transform point into screen space + TriWorldToScreen( point, screen ); + + if( i != 0 ) + { + // build world-space normal to screen-space direction vector + VectorSubtract( screen, screenLast, tmp ); + + // we don't need Z, we're in screen space + tmp[2] = 0; + VectorNormalize( tmp ); + VectorScale( RI.vup, -tmp[0], normal ); // Build point along noraml line (normal is -y, x) + VectorMA( normal, tmp[1], RI.vright, normal ); + + // Make a wide line + VectorMA( point, width, normal, last1 ); + VectorMA( point, -width, normal, last2 ); + + vLast += vStep; // advance texture scroll (v axis only) + TriTexCoord2f( 1, vLast ); + TriVertex3fv( last2 ); + TriTexCoord2f( 0, vLast ); + TriVertex3fv( last1 ); + } + + VectorCopy( screen, screenLast ); + noiseIndex += noiseStep; + } +} + +/* +================ +R_DrawDisk + +Draw beamdisk +================ +*/ +void R_DrawDisk( vec3_t source, vec3_t delta, float width, float scale, float freq, float speed, int segments ) +{ + float div, length, fraction; + float w, vLast, vStep; + vec3_t point; + int i; + + if( segments < 2 ) + return; + + if( segments > NOISE_DIVISIONS ) // UNDONE: Allow more segments? + segments = NOISE_DIVISIONS; + + length = VectorLength( delta ) * 0.01f; + if( length < 0.5f ) length = 0.5f; // don't lose all of the noise/texture on short beams + + div = 1.0f / (segments - 1); + vStep = length * div; // Texture length texels per space pixel + + // scroll speed 3.5 -- initial texture position, scrolls 3.5/sec (1.0 is entire texture) + vLast = fmod( freq * speed, 1 ); + scale = scale * length; + + // clamp the beam width + w = fmod( freq, width ) * delta[2]; + + // NOTE: we must force the degenerate triangles to be on the edge + for( i = 0; i < segments; i++ ) + { + float s, c; + + fraction = i * div; + VectorCopy( source, point ); + + TriBrightness( 1.0f ); + TriTexCoord2f( 1.0f, vLast ); + TriVertex3fv( point ); + + SinCos( fraction * M_PI2, &s, &c ); + point[0] = s * w + source[0]; + point[1] = c * w + source[1]; + point[2] = source[2]; + + TriBrightness( 1.0f ); + TriTexCoord2f( 0.0f, vLast ); + TriVertex3fv( point ); + + vLast += vStep; // advance texture scroll (v axis only) + } +} + +/* +================ +R_DrawCylinder + +Draw beam cylinder +================ +*/ +void R_DrawCylinder( vec3_t source, vec3_t delta, float width, float scale, float freq, float speed, int segments ) +{ + float div, length, fraction; + float vLast, vStep; + vec3_t point; + int i; + + if( segments < 2 ) + return; + + if( segments > NOISE_DIVISIONS ) + segments = NOISE_DIVISIONS; + + length = VectorLength( delta ) * 0.01f; + if( length < 0.5f ) length = 0.5f; // don't lose all of the noise/texture on short beams + + div = 1.0f / (segments - 1); + vStep = length * div; // texture length texels per space pixel + + // Scroll speed 3.5 -- initial texture position, scrolls 3.5/sec (1.0 is entire texture) + vLast = fmod( freq * speed, 1 ); + scale = scale * length; + + for ( i = 0; i < segments; i++ ) + { + float s, c; + + fraction = i * div; + SinCos( fraction * M_PI2, &s, &c ); + + point[0] = s * freq * delta[2] + source[0]; + point[1] = c * freq * delta[2] + source[1]; + point[2] = source[2] + width; + + TriBrightness( 0 ); + TriTexCoord2f( 1, vLast ); + TriVertex3fv( point ); + + point[0] = s * freq * ( delta[2] + width ) + source[0]; + point[1] = c * freq * ( delta[2] + width ) + source[1]; + point[2] = source[2] - width; + + TriBrightness( 1 ); + TriTexCoord2f( 0, vLast ); + TriVertex3fv( point ); + + vLast += vStep; // Advance texture scroll (v axis only) + } +} + +/* +============== +R_DrawBeamFollow + +drawi followed beam +============== +*/ +void R_DrawBeamFollow( BEAM *pbeam, float frametime ) +{ + particle_t *pnew, *particles; + float fraction, div, vLast, vStep, saved_fraction; + vec3_t last1, last2, tmp, screen, saved_last2; + vec3_t delta, screenLast, normal; + + gEngfuncs.R_FreeDeadParticles( &pbeam->particles ); + + particles = pbeam->particles; + pnew = NULL; + + div = 0; + if( FBitSet( pbeam->flags, FBEAM_STARTENTITY )) + { + if( particles ) + { + VectorSubtract( particles->org, pbeam->source, delta ); + div = VectorLength( delta ); + + if( div >= 32 ) + { + pnew = gEngfuncs.CL_AllocParticleFast(); + } + } + else + { + pnew = gEngfuncs.CL_AllocParticleFast(); + } + } + + if( pnew ) + { + VectorCopy( pbeam->source, pnew->org ); + pnew->die = gpGlobals->time + pbeam->amplitude; + VectorClear( pnew->vel ); + + pnew->next = particles; + pbeam->particles = pnew; + particles = pnew; + } + + // nothing to draw + if( !particles ) return; + + if( !pnew && div != 0 ) + { + VectorCopy( pbeam->source, delta ); + TriWorldToScreen( pbeam->source, screenLast ); + TriWorldToScreen( particles->org, screen ); + } + else if( particles && particles->next ) + { + VectorCopy( particles->org, delta ); + TriWorldToScreen( particles->org, screenLast ); + TriWorldToScreen( particles->next->org, screen ); + particles = particles->next; + } + else + { + return; + } + + // UNDONE: This won't work, screen and screenLast must be extrapolated here to fix the + // first beam segment for this trail + + // build world-space normal to screen-space direction vector + VectorSubtract( screen, screenLast, tmp ); + // we don't need Z, we're in screen space + tmp[2] = 0; + VectorNormalize( tmp ); + + // Build point along noraml line (normal is -y, x) + VectorScale( RI.vup, tmp[0], normal ); // Build point along normal line (normal is -y, x) + VectorMA( normal, tmp[1], RI.vright, normal ); + + // Make a wide line + VectorMA( delta, pbeam->width, normal, last1 ); + VectorMA( delta, -pbeam->width, normal, last2 ); + + div = 1.0 / pbeam->amplitude; + fraction = ( pbeam->die - gpGlobals->time ) * div; + + vLast = 0.0; + vStep = 1.0; + + while( particles ) + { + TriBrightness( fraction ); + TriTexCoord2f( 1, 1 ); + TriVertex3fv( last2 ); + TriBrightness( fraction ); + TriTexCoord2f( 0, 1 ); + TriVertex3fv( last1 ); + + VectorCopy( last2, saved_last2 ); + saved_fraction = fraction; + + // Transform point into screen space + TriWorldToScreen( particles->org, screen ); + // Build world-space normal to screen-space direction vector + VectorSubtract( screen, screenLast, tmp ); + + // we don't need Z, we're in screen space + tmp[2] = 0; + VectorNormalize( tmp ); + VectorScale( RI.vup, tmp[0], normal ); // Build point along noraml line (normal is -y, x) + VectorMA( normal, tmp[1], RI.vright, normal ); + + // Make a wide line + VectorMA( particles->org, pbeam->width, normal, last1 ); + VectorMA( particles->org, -pbeam->width, normal, last2 ); + + vLast += vStep; // Advance texture scroll (v axis only) + + if( particles->next != NULL ) + { + fraction = (particles->die - gpGlobals->time) * div; + } + else + { + fraction = 0.0; + } + + TriBrightness( fraction ); + TriTexCoord2f( 0, 0 ); + TriVertex3fv( last1 ); + TriBrightness( saved_fraction ); + TriTexCoord2f( 1.0f, 1.0f ); + TriVertex3fv( saved_last2 ); + + TriBrightness( fraction ); + TriTexCoord2f( 0.0f, 0.0f ); + TriVertex3fv( last1 ); + TriBrightness( fraction ); + TriTexCoord2f( 1, 0 ); + TriVertex3fv( last2 ); + + VectorCopy( screen, screenLast ); + + particles = particles->next; + } + + // drift popcorn trail if there is a velocity + particles = pbeam->particles; + + while( particles ) + { + VectorMA( particles->org, frametime, particles->vel, particles->org ); + particles = particles->next; + } +} + +/* +================ +R_DrawRing + +Draw beamring +================ +*/ +void R_DrawRing( vec3_t source, vec3_t delta, float width, float amplitude, float freq, float speed, int segments ) +{ + int i, j, noiseIndex, noiseStep; + float div, length, fraction, factor, vLast, vStep; + vec3_t last1, last2, point, screen, screenLast; + vec3_t tmp, normal, center, xaxis, yaxis; + float radius, x, y, scale; + + if( segments < 2 ) + return; + + VectorClear( screenLast ); + segments = segments * M_PI; + + if( segments > NOISE_DIVISIONS * 8 ) + segments = NOISE_DIVISIONS * 8; + + length = VectorLength( delta ) * 0.01f * M_PI; + if( length < 0.5f ) length = 0.5f; // Don't lose all of the noise/texture on short beams + + div = 1.0f / ( segments - 1 ); + + vStep = length * div / 8.0f; // texture length texels per space pixel + + // Scroll speed 3.5 -- initial texture position, scrolls 3.5/sec (1.0 is entire texture) + vLast = fmod( freq * speed, 1.0f ); + scale = amplitude * length / 8.0f; + + // Iterator to resample noise waveform (it needs to be generated in powers of 2) + noiseStep = (int)((float)( NOISE_DIVISIONS - 1 ) * div * 65536.0f ) * 8; + noiseIndex = 0; + + VectorScale( delta, 0.5f, delta ); + VectorAdd( source, delta, center ); + + VectorCopy( delta, xaxis ); + radius = VectorLength( xaxis ); + + // cull beamring + // -------------------------------- + // Compute box center +/- radius + VectorSet( last1, radius, radius, scale ); + VectorAdd( center, last1, tmp ); // maxs + VectorSubtract( center, last1, screen ); // mins + + if( !WORLDMODEL ) + return; + + // is that box in PVS && frustum? + if( !gEngfuncs.Mod_BoxVisible( screen, tmp, Mod_GetCurrentVis( )) ) //|| R_CullBox( screen, tmp )) + { + return; + } + + VectorSet( yaxis, xaxis[1], -xaxis[0], 0.0f ); + VectorNormalize( yaxis ); + VectorScale( yaxis, radius, yaxis ); + + j = segments / 8; + + for( i = 0; i < segments + 1; i++ ) + { + fraction = i * div; + SinCos( fraction * M_PI2, &x, &y ); + + VectorMAMAM( x, xaxis, y, yaxis, 1.0f, center, point ); + + // distort using noise + factor = rgNoise[(noiseIndex >> 16) & (NOISE_DIVISIONS - 1)] * scale; + VectorMA( point, factor, RI.vup, point ); + + // Rotate the noise along the perpendicluar axis a bit to keep the bolt from looking diagonal + factor = rgNoise[(noiseIndex >> 16) & (NOISE_DIVISIONS - 1)] * scale; + factor *= cos( fraction * M_PI * 24 + freq ); + VectorMA( point, factor, RI.vright, point ); + + // Transform point into screen space + TriWorldToScreen( point, screen ); + + if( i != 0 ) + { + // build world-space normal to screen-space direction vector + VectorSubtract( screen, screenLast, tmp ); + + // we don't need Z, we're in screen space + tmp[2] = 0; + VectorNormalize( tmp ); + + // Build point along normal line (normal is -y, x) + VectorScale( RI.vup, tmp[0], normal ); + VectorMA( normal, tmp[1], RI.vright, normal ); + + // Make a wide line + VectorMA( point, width, normal, last1 ); + VectorMA( point, -width, normal, last2 ); + + vLast += vStep; // Advance texture scroll (v axis only) + TriTexCoord2f( 1.0f, vLast ); + TriVertex3fv( last2 ); + TriTexCoord2f( 0.0f, vLast ); + TriVertex3fv( last1 ); + } + + VectorCopy( screen, screenLast ); + noiseIndex += noiseStep; + j--; + + if( j == 0 && amplitude != 0 ) + { + j = segments / 8; + FracNoise( rgNoise, NOISE_DIVISIONS ); + } + } +} + +/* +============== +R_BeamComputePoint + +compute attachment point for beam +============== +*/ +static qboolean R_BeamComputePoint( int beamEnt, vec3_t pt ) +{ + cl_entity_t *ent; + int attach; + + ent = gEngfuncs.R_BeamGetEntity( beamEnt ); + + if( beamEnt < 0 ) + attach = BEAMENT_ATTACHMENT( -beamEnt ); + else attach = BEAMENT_ATTACHMENT( beamEnt ); + + if( !ent ) + { + gEngfuncs.Con_DPrintf( S_ERROR "R_BeamComputePoint: invalid entity %i\n", BEAMENT_ENTITY( beamEnt )); + VectorClear( pt ); + return false; + } + + // get attachment + if( attach > 0 ) + VectorCopy( ent->attachment[attach - 1], pt ); + else if( ent->index == ENGINE_GET_PARM( PARM_PLAYER_INDEX ) ) + { + vec3_t simorg; + gEngfuncs.GetPredictedOrigin( simorg ); + VectorCopy( simorg, pt ); + } + else VectorCopy( ent->origin, pt ); + + return true; +} + +/* +============== +R_BeamRecomputeEndpoints + +Recomputes beam endpoints.. +============== +*/ +qboolean R_BeamRecomputeEndpoints( BEAM *pbeam ) +{ + if( FBitSet( pbeam->flags, FBEAM_STARTENTITY )) + { + cl_entity_t *start = gEngfuncs.R_BeamGetEntity( pbeam->startEntity ); + + if( R_BeamComputePoint( pbeam->startEntity, pbeam->source )) + { + if( !pbeam->pFollowModel ) + pbeam->pFollowModel = start->model; + SetBits( pbeam->flags, FBEAM_STARTVISIBLE ); + } + else if( !FBitSet( pbeam->flags, FBEAM_FOREVER )) + { + ClearBits( pbeam->flags, FBEAM_STARTENTITY ); + } + } + + if( FBitSet( pbeam->flags, FBEAM_ENDENTITY )) + { + cl_entity_t *end = gEngfuncs.R_BeamGetEntity( pbeam->endEntity ); + + if( R_BeamComputePoint( pbeam->endEntity, pbeam->target )) + { + if( !pbeam->pFollowModel ) + pbeam->pFollowModel = end->model; + SetBits( pbeam->flags, FBEAM_ENDVISIBLE ); + } + else if( !FBitSet( pbeam->flags, FBEAM_FOREVER )) + { + ClearBits( pbeam->flags, FBEAM_ENDENTITY ); + pbeam->die = gpGlobals->time; + return false; + } + else + { + return false; + } + } + + if( FBitSet( pbeam->flags, FBEAM_STARTENTITY ) && !FBitSet( pbeam->flags, FBEAM_STARTVISIBLE )) + return false; + return true; +} + + +/* +============== +R_BeamDraw + +Update beam vars and draw it +============== +*/ +void R_BeamDraw( BEAM *pbeam, float frametime ) +{ + model_t *model; + vec3_t delta; + + model = gEngfuncs.pfnGetModelByIndex( pbeam->modelIndex ); + SetBits( pbeam->flags, FBEAM_ISACTIVE ); + + if( !model || model->type != mod_sprite ) + { + pbeam->flags &= ~FBEAM_ISACTIVE; // force to ignore + pbeam->die = gpGlobals->time; + return; + } + + // update frequency + pbeam->freq += frametime; + + // generate fractal noise + if( frametime != 0.0f ) + { + rgNoise[0] = 0; + rgNoise[NOISE_DIVISIONS] = 0; + } + + if( pbeam->amplitude != 0 && frametime != 0.0f ) + { + if( FBitSet( pbeam->flags, FBEAM_SINENOISE )) + SineNoise( rgNoise, NOISE_DIVISIONS ); + else FracNoise( rgNoise, NOISE_DIVISIONS ); + } + + // update end points + if( FBitSet( pbeam->flags, FBEAM_STARTENTITY|FBEAM_ENDENTITY )) + { + // makes sure attachment[0] + attachment[1] are valid + if( !R_BeamRecomputeEndpoints( pbeam )) + { + ClearBits( pbeam->flags, FBEAM_ISACTIVE ); // force to ignore + return; + } + + // compute segments from the new endpoints + VectorSubtract( pbeam->target, pbeam->source, delta ); + VectorClear( pbeam->delta ); + + if( VectorLength( delta ) > 0.0000001f ) + VectorCopy( delta, pbeam->delta ); + + if( pbeam->amplitude >= 0.50f ) + pbeam->segments = VectorLength( pbeam->delta ) * 0.25f + 3.0f; // one per 4 pixels + else pbeam->segments = VectorLength( pbeam->delta ) * 0.075f + 3.0f; // one per 16 pixels + } + + if( pbeam->type == TE_BEAMPOINTS && R_BeamCull( pbeam->source, pbeam->target, 0 )) + { + ClearBits( pbeam->flags, FBEAM_ISACTIVE ); + return; + } + + // don't draw really short or inactive beams + if( !FBitSet( pbeam->flags, FBEAM_ISACTIVE ) || VectorLength( pbeam->delta ) < 0.1f ) + { + return; + } + + if( pbeam->flags & ( FBEAM_FADEIN|FBEAM_FADEOUT )) + { + // update life cycle + pbeam->t = pbeam->freq + ( pbeam->die - gpGlobals->time ); + if( pbeam->t != 0.0f ) pbeam->t = 1.0f - pbeam->freq / pbeam->t; + } + + if( pbeam->type == TE_BEAMHOSE ) + { + float flDot; + + VectorSubtract( pbeam->target, pbeam->source, delta ); + VectorNormalize( delta ); + + flDot = DotProduct( delta, RI.vforward ); + + // abort if the player's looking along it away from the source + if( flDot > 0 ) + { + return; + } + else + { + float flFade = pow( flDot, 10 ); + vec3_t localDir, vecProjection, tmp; + float flDistance; + + // fade the beam if the player's not looking at the source + VectorSubtract( RI.vieworg, pbeam->source, localDir ); + flDot = DotProduct( delta, localDir ); + VectorScale( delta, flDot, vecProjection ); + VectorSubtract( localDir, vecProjection, tmp ); + flDistance = VectorLength( tmp ); + + if( flDistance > 30 ) + { + flDistance = 1.0f - (( flDistance - 30.0f ) / 64.0f ); + if( flDistance <= 0 ) flFade = 0; + else flFade *= pow( flDistance, 3 ); + } + + if( flFade < ( 1.0f / 255.0f )) + return; + + // FIXME: needs to be testing + pbeam->brightness *= flFade; + } + } + + TriRenderMode( FBitSet( pbeam->flags, FBEAM_SOLID ) ? kRenderNormal : kRenderTransAdd ); + + if( !TriSpriteTexture( model, (int)(pbeam->frame + pbeam->frameRate * gpGlobals->time) % pbeam->frameCount )) + { + ClearBits( pbeam->flags, FBEAM_ISACTIVE ); + return; + } + + if( pbeam->type == TE_BEAMFOLLOW ) + { + cl_entity_t *pStart; + + // XASH SPECIFIC: get brightness from head entity + pStart = gEngfuncs.R_BeamGetEntity( pbeam->startEntity ); + if( pStart && pStart->curstate.rendermode != kRenderNormal ) + pbeam->brightness = gEngfuncs.CL_FxBlend( pStart ) / 255.0f; + } + + if( FBitSet( pbeam->flags, FBEAM_FADEIN )) + TriColor4f( pbeam->r, pbeam->g, pbeam->b, pbeam->t * pbeam->brightness ); + else if( FBitSet( pbeam->flags, FBEAM_FADEOUT )) + TriColor4f( pbeam->r, pbeam->g, pbeam->b, ( 1.0f - pbeam->t ) * pbeam->brightness ); + else TriColor4f( pbeam->r, pbeam->g, pbeam->b, pbeam->brightness ); + + switch( pbeam->type ) + { + case TE_BEAMTORUS: + //GL_Cull( GL_NONE ); + TriBegin( TRI_TRIANGLE_STRIP ); + R_DrawTorus( pbeam->source, pbeam->delta, pbeam->width, pbeam->amplitude, pbeam->freq, pbeam->speed, pbeam->segments ); + TriEnd(); + break; + case TE_BEAMDISK: + //GL_Cull( GL_NONE ); + TriBegin( TRI_TRIANGLE_STRIP ); + R_DrawDisk( pbeam->source, pbeam->delta, pbeam->width, pbeam->amplitude, pbeam->freq, pbeam->speed, pbeam->segments ); + TriEnd(); + break; + case TE_BEAMCYLINDER: + //GL_Cull( GL_NONE ); + TriBegin( TRI_TRIANGLE_STRIP ); + R_DrawCylinder( pbeam->source, pbeam->delta, pbeam->width, pbeam->amplitude, pbeam->freq, pbeam->speed, pbeam->segments ); + TriEnd(); + break; + case TE_BEAMPOINTS: + case TE_BEAMHOSE: + TriBegin( TRI_TRIANGLE_STRIP ); + R_DrawSegs( pbeam->source, pbeam->delta, pbeam->width, pbeam->amplitude, pbeam->freq, pbeam->speed, pbeam->segments, pbeam->flags ); + TriEnd(); + break; + case TE_BEAMFOLLOW: + TriBegin( TRI_TRIANGLES ); + R_DrawBeamFollow( pbeam, frametime ); + TriEnd(); + break; + case TE_BEAMRING: + //GL_Cull( GL_NONE ); + TriBegin( TRI_TRIANGLE_STRIP ); + R_DrawRing( pbeam->source, pbeam->delta, pbeam->width, pbeam->amplitude, pbeam->freq, pbeam->speed, pbeam->segments ); + TriEnd(); + break; + } + + //GL_Cull( GL_FRONT ); + r_stats.c_view_beams_count++; +} + +/* +============== +R_BeamSetAttributes + +set beam attributes +============== +*/ +static void R_BeamSetAttributes( BEAM *pbeam, float r, float g, float b, float framerate, int startFrame ) +{ + pbeam->frame = (float)startFrame; + pbeam->frameRate = framerate; + pbeam->r = r; + pbeam->g = g; + pbeam->b = b; +} + +/* +============== +R_BeamSetup + +generic function. all beams must be +passed through this +============== +*/ +static void R_BeamSetup( BEAM *pbeam, vec3_t start, vec3_t end, int modelIndex, float life, float width, float amplitude, float brightness, float speed ) +{ + model_t *sprite = gEngfuncs.pfnGetModelByIndex( modelIndex ); + + if( !sprite ) return; + + pbeam->type = BEAM_POINTS; + pbeam->modelIndex = modelIndex; + pbeam->frame = 0; + pbeam->frameRate = 0; + pbeam->frameCount = sprite->numframes; + + VectorCopy( start, pbeam->source ); + VectorCopy( end, pbeam->target ); + VectorSubtract( end, start, pbeam->delta ); + + pbeam->freq = speed * gpGlobals->time; + pbeam->die = life + gpGlobals->time; + pbeam->amplitude = amplitude; + pbeam->brightness = brightness; + pbeam->width = width; + pbeam->speed = speed; + + if( amplitude >= 0.50f ) + pbeam->segments = VectorLength( pbeam->delta ) * 0.25f + 3.0f; // one per 4 pixels + else pbeam->segments = VectorLength( pbeam->delta ) * 0.075f + 3.0f; // one per 16 pixels + + pbeam->pFollowModel = NULL; + pbeam->flags = 0; +} + + + +/* +============== +R_BeamDrawCustomEntity + +initialize beam from server entity +============== +*/ +void R_BeamDrawCustomEntity( cl_entity_t *ent ) +{ + BEAM beam; + float amp = ent->curstate.body / 100.0f; + float blend = gEngfuncs.CL_FxBlend( ent ) / 255.0f; + float r, g, b; + int beamFlags; + + r = ent->curstate.rendercolor.r / 255.0f; + g = ent->curstate.rendercolor.g / 255.0f; + b = ent->curstate.rendercolor.b / 255.0f; + + R_BeamSetup( &beam, ent->origin, ent->angles, ent->curstate.modelindex, 0, ent->curstate.scale, amp, blend, ent->curstate.animtime ); + R_BeamSetAttributes( &beam, r, g, b, ent->curstate.framerate, ent->curstate.frame ); + beam.pFollowModel = NULL; + + switch( ent->curstate.rendermode & 0x0F ) + { + case BEAM_ENTPOINT: + beam.type = TE_BEAMPOINTS; + if( ent->curstate.sequence ) + { + SetBits( beam.flags, FBEAM_STARTENTITY ); + beam.startEntity = ent->curstate.sequence; + } + if( ent->curstate.skin ) + { + SetBits( beam.flags, FBEAM_ENDENTITY ); + beam.endEntity = ent->curstate.skin; + } + break; + case BEAM_ENTS: + beam.type = TE_BEAMPOINTS; + SetBits( beam.flags, FBEAM_STARTENTITY | FBEAM_ENDENTITY ); + beam.startEntity = ent->curstate.sequence; + beam.endEntity = ent->curstate.skin; + break; + case BEAM_HOSE: + beam.type = TE_BEAMHOSE; + break; + case BEAM_POINTS: + // already set up + break; + } + + beamFlags = ( ent->curstate.rendermode & 0xF0 ); + + if( FBitSet( beamFlags, BEAM_FSINE )) + SetBits( beam.flags, FBEAM_SINENOISE ); + + if( FBitSet( beamFlags, BEAM_FSOLID )) + SetBits( beam.flags, FBEAM_SOLID ); + + if( FBitSet( beamFlags, BEAM_FSHADEIN )) + SetBits( beam.flags, FBEAM_SHADEIN ); + + if( FBitSet( beamFlags, BEAM_FSHADEOUT )) + SetBits( beam.flags, FBEAM_SHADEOUT ); + + // draw it + R_BeamDraw( &beam, tr.frametime ); +} + + +/* +============== +CL_DrawBeams + +draw beam loop +============== +*/ +void CL_DrawBeams( int fTrans, BEAM *active_beams ) +{ + BEAM *pBeam; + int i, flags; + + //pglShadeModel( GL_SMOOTH ); + //pglDepthMask( fTrans ? GL_FALSE : GL_TRUE ); + + // server beams don't allocate beam chains + // all params are stored in cl_entity_t + for( i = 0; i < tr.draw_list->num_beam_entities; i++ ) + { + RI.currentbeam = tr.draw_list->beam_entities[i]; + flags = RI.currentbeam->curstate.rendermode & 0xF0; + + if( fTrans && FBitSet( flags, FBEAM_SOLID )) + continue; + + if( !fTrans && !FBitSet( flags, FBEAM_SOLID )) + continue; + + R_BeamDrawCustomEntity( RI.currentbeam ); + r_stats.c_view_beams_count++; + } + + RI.currentbeam = NULL; + + // draw temporary entity beams + for( pBeam = active_beams; pBeam; pBeam = pBeam->next ) + { + if( fTrans && FBitSet( pBeam->flags, FBEAM_SOLID )) + continue; + + if( !fTrans && !FBitSet( pBeam->flags, FBEAM_SOLID )) + continue; + + R_BeamDraw( pBeam, gpGlobals->time - gpGlobals->oldtime ); + } + + //pglShadeModel( GL_FLAT ); + //pglDepthMask( GL_TRUE ); +} diff --git a/r_context.c b/r_context.c index 9e3f0307..ceeede80 100644 --- a/r_context.c +++ b/r_context.c @@ -132,10 +132,10 @@ qboolean Mod_ProcessRenderData( model_t *mod, qboolean create, const byte *buf ) switch( mod->type ) { case mod_studio: - // Mod_LoadStudioModel( mod, buf, loaded ); + //Mod_LoadStudioModel( mod, buf, loaded ); break; case mod_sprite: - //Mod_LoadSpriteModel( mod, buf, &loaded, mod->numtexinfo ); + Mod_LoadSpriteModel( mod, buf, &loaded, mod->numtexinfo ); break; case mod_alias: //Mod_LoadAliasModel( mod, buf, &loaded ); @@ -306,7 +306,7 @@ void Mod_UnloadTextures( model_t *mod ) Mod_BrushUnloadTextures( mod ); break; case mod_sprite: - //Mod_SpriteUnloadTextures( mod->cache.data ); + Mod_SpriteUnloadTextures( mod->cache.data ); break; default: gEngfuncs.Host_Error( "Mod_UnloadModel: unsupported type %d\n", mod->type ); } @@ -357,11 +357,6 @@ void GL_SetRenderMode(int mode) /// maybe, setup block drawing function pointers here } -void CL_AddCustomBeam(cl_entity_t *pEnvBeam) -{ - // same for beams -} - void R_ShowTextures() { // textures undone too @@ -397,31 +392,6 @@ void GL_SubdivideSurface(msurface_t *fa) } -void Mod_LoadMapSprite(model_t *mod, const void *buffer, size_t size, qboolean *loaded) -{ - -} - -void CL_DrawParticles(double frametime, particle_t *cl_active_particles, float partsize) -{ - -} - -void CL_DrawBeams(int fTrans, BEAM *active_beams) -{ - -} - -void CL_DrawTracers(double frametime, particle_t *cl_active_tracers) -{ - -} - -qboolean R_BeamCull(const vec3_t start, const vec3_t end, qboolean pvsOnly) -{ - return false; -} - void DrawSingleDecal(decal_t *pDecal, msurface_t *fa) { @@ -457,11 +427,6 @@ void GL_TextureTarget(uint target) } -void CL_DrawParticlesExternal(const ref_viewpass_t *rvp, qboolean trans_pass, float frametime) -{ - // no renderapi support -} - void GL_BuildLightmaps() { CL_RunLightStyles(); diff --git a/r_draw.c b/r_draw.c index cd6aa659..8cd3c79b 100644 --- a/r_draw.c +++ b/r_draw.c @@ -42,11 +42,11 @@ void R_GetSpriteParms( int *frameWidth, int *frameHeight, int *numFrames, int cu mspriteframe_t *pFrame; if( !pSprite || pSprite->type != mod_sprite ) return; // bad model ? - //pFrame = R_GetSpriteFrame( pSprite, currentFrame, 0.0f ); + pFrame = R_GetSpriteFrame( pSprite, currentFrame, 0.0f ); - //if( frameWidth ) *frameWidth = pFrame->width; -// if( frameHeight ) *frameHeight = pFrame->height; - //if( numFrames ) *numFrames = pSprite->numframes; + if( frameWidth ) *frameWidth = pFrame->width; + if( frameHeight ) *frameHeight = pFrame->height; + if( numFrames ) *numFrames = pSprite->numframes; } int R_GetSpriteTexture( const model_t *m_pSpriteModel, int frame ) @@ -54,7 +54,7 @@ int R_GetSpriteTexture( const model_t *m_pSpriteModel, int frame ) if( !m_pSpriteModel || m_pSpriteModel->type != mod_sprite || !m_pSpriteModel->cache.data ) return 0; - return 0;//R_GetSpriteFrame( m_pSpriteModel, frame, 0.0f )->gl_texturenum; + return R_GetSpriteFrame( m_pSpriteModel, frame, 0.0f )->gl_texturenum; } diff --git a/r_image.c b/r_image.c index e72903fb..bf577aaf 100644 --- a/r_image.c +++ b/r_image.c @@ -502,7 +502,7 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) GL_SetTextureDimensions( tex, pic->width, pic->height, pic->depth ); GL_SetTextureFormat( tex, pic->type, pic->flags ); - gEngfuncs.Con_Printf("%s %d %d\n", tex->name, tex->width, tex->height ); + //gEngfuncs.Con_Printf("%s %d %d\n", tex->name, tex->width, tex->height ); Assert( pic != NULL ); Assert( tex != NULL ); @@ -533,7 +533,7 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) //GL_TextureImageRAW( tex, i, j, width, height, tex->depth, pic->type, data ); // increase size to workaround triangle renderer bugs // it seems to assume memory readable. maybe it was pointed to WAD? - tex->pixels[j] = (byte*)Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 256 ) + 128; + tex->pixels[j] = (byte*)Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 1024 ) + 512; if( j == 0 && tex->flags & TF_HAS_ALPHA ) tex->alpha_pixels = (byte*)Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 256 ) + 128; diff --git a/r_local.h b/r_local.h index 6f843611..546b6b79 100644 --- a/r_local.h +++ b/r_local.h @@ -394,13 +394,13 @@ void GL_Cull( unsigned int cull ); void R_ShowTextures( void ); void R_ShowTree( void ); void SCR_TimeRefresh_f( void ); - +#endif // // gl_beams.c // void CL_DrawBeams( int fTrans, BEAM *active_beams ); qboolean R_BeamCull( const vec3_t start, const vec3_t end, qboolean pvsOnly ); - +#if 0 // // gl_cull.c // @@ -534,7 +534,7 @@ void GL_ResetFogColor( void ); void R_GenerateVBO(); void R_ClearVBO(); void R_AddDecalVBO( decal_t *pdecal, msurface_t *surf ); - +#endif // // gl_rpart.c // @@ -550,7 +550,7 @@ void R_SpriteInit( void ); void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags ); mspriteframe_t *R_GetSpriteFrame( const model_t *pModel, int frame, float yaw ); void R_DrawSpriteModel( cl_entity_t *e ); -#endif + // // gl_studio.c // @@ -679,7 +679,7 @@ void TriVertex3fv( const float *v ); void TriVertex3f( float x, float y, float z ); void _TriColor4f( float r, float g, float b, float a ); void TriColor4ub( byte r, byte g, byte b, byte a ); -int TriWorldToScreen( float *world, float *screen ); +int TriWorldToScreen( const float *world, float *screen ); int TriSpriteTexture( model_t *pSpriteModel, int frame ); void TriFog( float flFogColor[3], float flStart, float flEnd, int bOn ); void TriGetMatrix( const int pname, float *matrix ); @@ -1225,10 +1225,15 @@ extern cvar_t *sw_surfcacheoverride; extern cvar_t *sw_waterwarp; extern cvar_t *sw_texfilt; extern cvar_t *r_decals; - +extern cvar_t *r_traceglow; extern cvar_t *sw_notransbrushes; extern cvar_t *sw_noalphabrushes; +extern cvar_t *tracerred; +extern cvar_t *tracergreen; +extern cvar_t *tracerblue; +extern cvar_t *traceralpha; + extern vec3_t modelorg; diff --git a/r_main.c b/r_main.c index 13b1deef..6283efae 100644 --- a/r_main.c +++ b/r_main.c @@ -94,6 +94,12 @@ cvar_t *r_lerpmodels; cvar_t *r_novis; cvar_t *r_lightmap; cvar_t *r_dynamic; +cvar_t *r_traceglow; + +cvar_t *tracerred; +cvar_t *tracergreen; +cvar_t *tracerblue; +cvar_t *traceralpha; cvar_t *r_speeds; cvar_t *r_lightlevel; //FIXME HACK @@ -1091,6 +1097,7 @@ void R_DrawEntitiesOnList( void ) // GL_CheckForErrors(); + R_SetUpWorldTransform(); // draw sprites seperately, because of alpha blending for( i = 0; i < tr.draw_list->num_solid_entities && !RI.onlyClientDraw; i++ ) { @@ -1103,7 +1110,7 @@ void R_DrawEntitiesOnList( void ) switch( RI.currentmodel->type ) { case mod_sprite: - // R_DrawSpriteModel( RI.currententity ); + R_DrawSpriteModel( RI.currententity ); break; } } @@ -1133,7 +1140,7 @@ void R_DrawEntitiesOnList( void ) tr.blend = gEngfuncs.CL_FxBlend( RI.currententity ) / 255.0f; else tr.blend = 1.0f; // draw as solid but sorted by distance - //if( tr.blend <= 0.0f ) continue; + if( tr.blend <= 0.0f ) continue; Assert( RI.currententity != NULL ); Assert( RI.currentmodel != NULL ); @@ -1151,7 +1158,8 @@ void R_DrawEntitiesOnList( void ) R_DrawStudioModel( RI.currententity ); break; case mod_sprite: - // R_DrawSpriteModel( RI.currententity ); + R_SetUpWorldTransform(); + R_DrawSpriteModel( RI.currententity ); break; default: break; @@ -1963,6 +1971,7 @@ qboolean R_Init() sw_waterwarp = gEngfuncs.Cvar_Get ("sw_waterwarp", "1", 0, ""); sw_notransbrushes = gEngfuncs.Cvar_Get( "sw_notransbrushes", "0", FCVAR_ARCHIVE, "do not apply transparency to water/glasses (faster)"); sw_noalphabrushes = gEngfuncs.Cvar_Get( "sw_noalphabrushes", "0", FCVAR_ARCHIVE, "do not draw brush holes (faster)"); + r_traceglow = gEngfuncs.Cvar_Get( "r_traceglow", "1", FCVAR_ARCHIVE, "cull flares behind models" ); sw_texfilt = gEngfuncs.Cvar_Get ("sw_texfilt", "0", 0, "texture dither"); //r_lefthand = ri.Cvar_Get( "hand", "0", FCVAR_USERINFO | FCVAR_ARCHIVE ); @@ -1974,6 +1983,11 @@ qboolean R_Init() //r_lerpmodels = ri.Cvar_Get( "r_lerpmodels", "1", 0 ); r_novis = gEngfuncs.Cvar_Get( "r_novis", "0", 0, "" ); + tracerred = gEngfuncs.Cvar_Get( "tracerred", "0.8", 0, "tracer red component weight ( 0 - 1.0 )" ); + tracergreen = gEngfuncs.Cvar_Get( "tracergreen", "0.8", 0, "tracer green component weight ( 0 - 1.0 )" ); + tracerblue = gEngfuncs.Cvar_Get( "tracerblue", "0.4", 0, "tracer blue component weight ( 0 - 1.0 )" ); + traceralpha = gEngfuncs.Cvar_Get( "traceralpha", "0.5", 0, "tracer alpha amount ( 0 - 1.0 )" ); + // create the window and set up the context r_temppool = Mem_AllocPool( "ref_sw zone" ); @@ -1998,6 +2012,7 @@ qboolean R_Init() view_clipplanes[1].leftedge = view_clipplanes[2].leftedge =view_clipplanes[3].leftedge = false; view_clipplanes[0].rightedge = view_clipplanes[2].rightedge = view_clipplanes[3].rightedge = false; R_StudioInit(); + R_SpriteInit(); R_InitTurb(); return true; diff --git a/r_part.c b/r_part.c new file mode 100644 index 00000000..02c10ab3 --- /dev/null +++ b/r_part.c @@ -0,0 +1,300 @@ +/* +cl_part.c - particles and tracers +Copyright (C) 2010 Uncle Mike + +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 3 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. +*/ + +#include "r_local.h" +#include "r_efx.h" +#include "event_flags.h" +#include "entity_types.h" +#include "triangleapi.h" +#include "pm_local.h" +#include "cl_tent.h" +#include "studio.h" + +static float gTracerSize[11] = { 1.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f }; +static color24 gTracerColors[] = +{ +{ 255, 255, 255 }, // White +{ 255, 0, 0 }, // Red +{ 0, 255, 0 }, // Green +{ 0, 0, 255 }, // Blue +{ 0, 0, 0 }, // Tracer default, filled in from cvars, etc. +{ 255, 167, 17 }, // Yellow-orange sparks +{ 255, 130, 90 }, // Yellowish streaks (garg) +{ 55, 60, 144 }, // Blue egon streak +{ 255, 130, 90 }, // More Yellowish streaks (garg) +{ 255, 140, 90 }, // More Yellowish streaks (garg) +{ 200, 130, 90 }, // More red streaks (garg) +{ 255, 120, 70 }, // Darker red streaks (garg) +}; + +/* +================ +CL_DrawParticles + +update particle color, position, free expired and draw it +================ +*/ +void CL_DrawParticles( double frametime, particle_t *cl_active_particles, float partsize ) +{ + particle_t *p; + vec3_t right, up; + color24 *pColor; + int alpha; + float size; + + if( !cl_active_particles ) + return; // nothing to draw? + + //pglEnable( GL_BLEND ); + //pglDisable( GL_ALPHA_TEST ); + //pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + + GL_Bind( XASH_TEXTURE0, tr.particleTexture ); + //pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + //pglDepthMask( GL_FALSE ); + + TriBegin( TRI_QUADS ); + + for( p = cl_active_particles; p; p = p->next ) + { + if(( p->type != pt_blob ) || ( p->packedColor == 255 )) + { + size = partsize; // get initial size of particle + + // scale up to keep particles from disappearing + size += (p->org[0] - RI.vieworg[0]) * RI.cull_vforward[0]; + size += (p->org[1] - RI.vieworg[1]) * RI.cull_vforward[1]; + size += (p->org[2] - RI.vieworg[2]) * RI.cull_vforward[2]; + + if( size < 20.0f ) size = partsize; + else size = partsize + size * 0.002f; + + // scale the axes by radius + VectorScale( RI.cull_vright, size, right ); + VectorScale( RI.cull_vup, size, up ); + + p->color = bound( 0, p->color, 255 ); + pColor = gEngfuncs.CL_GetPaletteColor( p->color ); + + alpha = 255 * (p->die - gpGlobals->time) * 16.0f; + if( alpha > 255 || p->type == pt_static ) + alpha = 255; + + TriColor4ub( gEngfuncs.LightToTexGamma( pColor->r ), + gEngfuncs.LightToTexGamma( pColor->g ), + gEngfuncs.LightToTexGamma( pColor->b ), alpha ); + + TriTexCoord2f( 0.0f, 1.0f ); + TriVertex3f( p->org[0] - right[0] + up[0], p->org[1] - right[1] + up[1], p->org[2] - right[2] + up[2] ); + TriTexCoord2f( 0.0f, 0.0f ); + TriVertex3f( p->org[0] + right[0] + up[0], p->org[1] + right[1] + up[1], p->org[2] + right[2] + up[2] ); + TriTexCoord2f( 1.0f, 0.0f ); + TriVertex3f( p->org[0] + right[0] - up[0], p->org[1] + right[1] - up[1], p->org[2] + right[2] - up[2] ); + TriTexCoord2f( 1.0f, 1.0f ); + TriVertex3f( p->org[0] - right[0] - up[0], p->org[1] - right[1] - up[1], p->org[2] - right[2] - up[2] ); + r_stats.c_particle_count++; + } + + gEngfuncs.CL_ThinkParticle( frametime, p ); + } + + TriEnd(); + //pglDepthMask( GL_TRUE ); +} + +/* +================ +CL_CullTracer + +check tracer bbox +================ +*/ +static qboolean CL_CullTracer( particle_t *p, const vec3_t start, const vec3_t end ) +{ + vec3_t mins, maxs; + int i; + return false; +/* + // compute the bounding box + for( i = 0; i < 3; i++ ) + { + if( start[i] < end[i] ) + { + mins[i] = start[i]; + maxs[i] = end[i]; + } + else + { + mins[i] = end[i]; + maxs[i] = start[i]; + } + + // don't let it be zero sized + if( mins[i] == maxs[i] ) + { + maxs[i] += gTracerSize[p->type] * 2.0f; + } + } + + // check bbox + return R_CullBox( mins, maxs );*/ +} + +/* +================ +CL_DrawTracers + +update tracer color, position, free expired and draw it +================ +*/ +void CL_DrawTracers( double frametime, particle_t *cl_active_tracers ) +{ + float scale, atten, gravity; + vec3_t screenLast, screen; + vec3_t start, end, delta; + particle_t *p; + + // update tracer color if this is changed + if( FBitSet( tracerred->flags|tracergreen->flags|tracerblue->flags|traceralpha->flags, FCVAR_CHANGED )) + { + color24 *customColors = &gTracerColors[4]; + customColors->r = (byte)(tracerred->value * traceralpha->value * 255); + customColors->g = (byte)(tracergreen->value * traceralpha->value * 255); + customColors->b = (byte)(tracerblue->value * traceralpha->value * 255); + ClearBits( tracerred->flags, FCVAR_CHANGED ); + ClearBits( tracergreen->flags, FCVAR_CHANGED ); + ClearBits( tracerblue->flags, FCVAR_CHANGED ); + ClearBits( traceralpha->flags, FCVAR_CHANGED ); + } + + if( !cl_active_tracers ) + return; // nothing to draw? + + if( !TriSpriteTexture( gEngfuncs.GetDefaultSprite( REF_DOT_SPRITE ), 0 )) + return; + + //pglEnable( GL_BLEND ); + //pglBlendFunc( GL_SRC_ALPHA, GL_ONE ); + //pglDisable( GL_ALPHA_TEST ); + //pglDepthMask( GL_FALSE ); + + gravity = frametime * MOVEVARS->gravity; + scale = 1.0 - (frametime * 0.9); + if( scale < 0.0f ) scale = 0.0f; + + for( p = cl_active_tracers; p; p = p->next ) + { + atten = (p->die - gpGlobals->time); + if( atten > 0.1f ) atten = 0.1f; + + VectorScale( p->vel, ( p->ramp * atten ), delta ); + VectorAdd( p->org, delta, end ); + VectorCopy( p->org, start ); + + if( !CL_CullTracer( p, start, end )) + { + vec3_t verts[4], tmp2; + vec3_t tmp, normal; + color24 *pColor; + + // Transform point into screen space + TriWorldToScreen( start, screen ); + TriWorldToScreen( end, screenLast ); + + // build world-space normal to screen-space direction vector + VectorSubtract( screen, screenLast, tmp ); + + // we don't need Z, we're in screen space + tmp[2] = 0; + VectorNormalize( tmp ); + + // build point along noraml line (normal is -y, x) + VectorScale( RI.cull_vup, tmp[0] * gTracerSize[p->type], normal ); + VectorScale( RI.cull_vright, -tmp[1] * gTracerSize[p->type], tmp2 ); + VectorSubtract( normal, tmp2, normal ); + + // compute four vertexes + VectorSubtract( start, normal, verts[0] ); + VectorAdd( start, normal, verts[1] ); + VectorAdd( verts[0], delta, verts[2] ); + VectorAdd( verts[1], delta, verts[3] ); + + if( p->color > sizeof( gTracerColors ) / sizeof( color24 ) ) + { + gEngfuncs.Con_Printf( S_ERROR "UserTracer with color > %d\n", sizeof( gTracerColors ) / sizeof( color24 )); + p->color = 0; + } + + pColor = &gTracerColors[p->color]; + TriColor4ub( pColor->r, pColor->g, pColor->b, p->packedColor ); + + TriBegin( TRI_QUADS ); + TriTexCoord2f( 0.0f, 0.8f ); + TriVertex3fv( verts[2] ); + TriTexCoord2f( 1.0f, 0.8f ); + TriVertex3fv( verts[3] ); + TriTexCoord2f( 1.0f, 0.0f ); + TriVertex3fv( verts[1] ); + TriTexCoord2f( 0.0f, 0.0f ); + TriVertex3fv( verts[0] ); + TriEnd(); + } + + // evaluate position + VectorMA( p->org, frametime, p->vel, p->org ); + + if( p->type == pt_grav ) + { + p->vel[0] *= scale; + p->vel[1] *= scale; + p->vel[2] -= gravity; + + p->packedColor = 255 * (p->die - gpGlobals->time) * 2; + if( p->packedColor > 255 ) p->packedColor = 255; + } + else if( p->type == pt_slowgrav ) + { + p->vel[2] = gravity * 0.05; + } + } + + //pglDepthMask( GL_TRUE ); +} + +/* +=============== +CL_DrawParticlesExternal + +allow to draw effects from custom renderer +=============== +*/ +void CL_DrawParticlesExternal( const ref_viewpass_t *rvp, qboolean trans_pass, float frametime ) +{ + ref_instance_t oldRI = RI; + + memcpy( &oldRI, &RI, sizeof( ref_instance_t )); + R_SetupRefParams( rvp ); + R_SetupFrustum(); +// R_SetupGL( false ); // don't touch GL-states + + // setup PVS for frame + memcpy( RI.visbytes, tr.visbytes, gpGlobals->visbytes ); + tr.frametime = frametime; + + gEngfuncs.CL_DrawEFX( frametime, trans_pass ); + + // restore internal state + memcpy( &RI, &oldRI, sizeof( ref_instance_t )); +} diff --git a/r_sprite.c b/r_sprite.c new file mode 100644 index 00000000..b6afac8e --- /dev/null +++ b/r_sprite.c @@ -0,0 +1,1087 @@ +/* +gl_sprite.c - sprite rendering +Copyright (C) 2010 Uncle Mike + +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 3 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. +*/ + +#include "r_local.h" +#include "pm_local.h" +#include "sprite.h" +#include "studio.h" +#include "entity_types.h" +//#include "cl_tent.h" + +// it's a Valve default value for LoadMapSprite (probably must be power of two) +#define MAPSPRITE_SIZE 128 +#define GLARE_FALLOFF 19000.0f + +cvar_t *r_sprite_lerping; +cvar_t *r_sprite_lighting; +char sprite_name[MAX_QPATH]; +char group_suffix[8]; +static uint r_texFlags = 0; +static int sprite_version; +float sprite_radius; + +/* +==================== +R_SpriteInit + +==================== +*/ +void R_SpriteInit( void ) +{ + r_sprite_lerping = gEngfuncs.Cvar_Get( "r_sprite_lerping", "1", FCVAR_ARCHIVE, "enables sprite animation lerping" ); + r_sprite_lighting = gEngfuncs.Cvar_Get( "r_sprite_lighting", "1", FCVAR_ARCHIVE, "enables sprite lighting (blood etc)" ); +} + +/* +==================== +R_SpriteLoadFrame + +upload a single frame +==================== +*/ +static dframetype_t *R_SpriteLoadFrame( model_t *mod, void *pin, mspriteframe_t **ppframe, int num ) +{ + dspriteframe_t *pinframe; + mspriteframe_t *pspriteframe; + int gl_texturenum = 0; + char texname[128]; + int bytes = 1; + + pinframe = (dspriteframe_t *)pin; + if( sprite_version == SPRITE_VERSION_32 ) + bytes = 4; + + // build uinque frame name + if( FBitSet( mod->flags, MODEL_CLIENT )) // it's a HUD sprite + { + Q_snprintf( texname, sizeof( texname ), "#HUD/%s(%s:%i%i).spr", sprite_name, group_suffix, num / 10, num % 10 ); + gl_texturenum = GL_LoadTexture( texname, pin, pinframe->width * pinframe->height * bytes, r_texFlags ); + } + else + { + Q_snprintf( texname, sizeof( texname ), "#%s(%s:%i%i).spr", sprite_name, group_suffix, num / 10, num % 10 ); + gl_texturenum = GL_LoadTexture( texname, pin, pinframe->width * pinframe->height * bytes, r_texFlags ); + } + + // setup frame description + pspriteframe = Mem_Malloc( mod->mempool, sizeof( mspriteframe_t )); + pspriteframe->width = pinframe->width; + pspriteframe->height = pinframe->height; + pspriteframe->up = pinframe->origin[1]; + pspriteframe->left = pinframe->origin[0]; + pspriteframe->down = pinframe->origin[1] - pinframe->height; + pspriteframe->right = pinframe->width + pinframe->origin[0]; + pspriteframe->gl_texturenum = gl_texturenum; + *ppframe = pspriteframe; + + return (dframetype_t *)((byte *)(pinframe + 1) + pinframe->width * pinframe->height * bytes ); +} + +/* +==================== +R_SpriteLoadGroup + +upload a group frames +==================== +*/ +static dframetype_t *R_SpriteLoadGroup( model_t *mod, void *pin, mspriteframe_t **ppframe, int framenum ) +{ + dspritegroup_t *pingroup; + mspritegroup_t *pspritegroup; + dspriteinterval_t *pin_intervals; + float *poutintervals; + int i, groupsize, numframes; + void *ptemp; + + pingroup = (dspritegroup_t *)pin; + numframes = pingroup->numframes; + + groupsize = sizeof( mspritegroup_t ) + (numframes - 1) * sizeof( pspritegroup->frames[0] ); + pspritegroup = Mem_Calloc( mod->mempool, groupsize ); + pspritegroup->numframes = numframes; + + *ppframe = (mspriteframe_t *)pspritegroup; + pin_intervals = (dspriteinterval_t *)(pingroup + 1); + poutintervals = Mem_Calloc( mod->mempool, numframes * sizeof( float )); + pspritegroup->intervals = poutintervals; + + for( i = 0; i < numframes; i++ ) + { + *poutintervals = pin_intervals->interval; + if( *poutintervals <= 0.0f ) + *poutintervals = 1.0f; // set error value + poutintervals++; + pin_intervals++; + } + + ptemp = (void *)pin_intervals; + for( i = 0; i < numframes; i++ ) + { + ptemp = R_SpriteLoadFrame( mod, ptemp, &pspritegroup->frames[i], framenum * 10 + i ); + } + + return (dframetype_t *)ptemp; +} + +/* +==================== +Mod_LoadSpriteModel + +load sprite model +==================== +*/ +void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags ) +{ + const dsprite_t *pin; + const short *numi = NULL; + const dframetype_t *pframetype; + msprite_t *psprite; + int i; + + pin = buffer; + psprite = mod->cache.data; + + if( pin->version == SPRITE_VERSION_Q1 || pin->version == SPRITE_VERSION_32 ) + numi = NULL; + else if( pin->version == SPRITE_VERSION_HL ) + numi = (const short *)((const byte*)buffer + sizeof( dsprite_hl_t )); + + r_texFlags = texFlags; + sprite_version = pin->version; + Q_strncpy( sprite_name, mod->name, sizeof( sprite_name )); + COM_StripExtension( sprite_name ); + + if( numi == NULL ) + { + rgbdata_t *pal; + + pal = gEngfuncs.FS_LoadImage( "#id.pal", (byte *)&i, 768 ); + pframetype = (const dframetype_t *)((const byte*)buffer + sizeof( dsprite_q1_t )); // pinq1 + 1 + gEngfuncs.FS_FreeImage( pal ); // palette installed, no reason to keep this data + } + else if( *numi == 256 ) + { + const byte *src = (const byte *)(numi+1); + rgbdata_t *pal; + + // install palette + switch( psprite->texFormat ) + { + case SPR_INDEXALPHA: + pal = gEngfuncs.FS_LoadImage( "#gradient.pal", src, 768 ); + break; + case SPR_ALPHTEST: + pal = gEngfuncs.FS_LoadImage( "#masked.pal", src, 768 ); + break; + default: + pal = gEngfuncs.FS_LoadImage( "#normal.pal", src, 768 ); + break; + } + + pframetype = (const dframetype_t *)(src + 768); + gEngfuncs.FS_FreeImage( pal ); // palette installed, no reason to keep this data + } + else + { + gEngfuncs.Con_DPrintf( S_ERROR "%s has wrong number of palette colors %i (should be 256)\n", mod->name, *numi ); + return; + } + + if( mod->numframes < 1 ) + return; + + for( i = 0; i < mod->numframes; i++ ) + { + frametype_t frametype = pframetype->type; + psprite->frames[i].type = frametype; + + switch( frametype ) + { + case FRAME_SINGLE: + Q_strncpy( group_suffix, "frame", sizeof( group_suffix )); + pframetype = R_SpriteLoadFrame( mod, pframetype + 1, &psprite->frames[i].frameptr, i ); + break; + case FRAME_GROUP: + Q_strncpy( group_suffix, "group", sizeof( group_suffix )); + pframetype = R_SpriteLoadGroup( mod, pframetype + 1, &psprite->frames[i].frameptr, i ); + break; + case FRAME_ANGLED: + Q_strncpy( group_suffix, "angle", sizeof( group_suffix )); + pframetype = R_SpriteLoadGroup( mod, pframetype + 1, &psprite->frames[i].frameptr, i ); + break; + } + if( pframetype == NULL ) break; // technically an error + } + + if( loaded ) *loaded = true; // done +} + +/* +==================== +Mod_LoadMapSprite + +Loading a bitmap image as sprite with multiple frames +as pieces of input image +==================== +*/ +void Mod_LoadMapSprite( model_t *mod, const void *buffer, size_t size, qboolean *loaded ) +{ + byte *src, *dst; + rgbdata_t *pix, temp; + char texname[128]; + int i, j, x, y, w, h; + int xl, yl, xh, yh; + int linedelta, numframes; + mspriteframe_t *pspriteframe; + msprite_t *psprite; + + if( loaded ) *loaded = false; + Q_snprintf( texname, sizeof( texname ), "#%s", mod->name ); + gEngfuncs.Image_SetForceFlags( IL_OVERVIEW ); + pix = gEngfuncs.FS_LoadImage( texname, buffer, size ); + gEngfuncs.Image_ClearForceFlags(); + if( !pix ) return; // bad image or something else + + mod->type = mod_sprite; + r_texFlags = 0; // no custom flags for map sprites + + if( pix->width % MAPSPRITE_SIZE ) + w = pix->width - ( pix->width % MAPSPRITE_SIZE ); + else w = pix->width; + + if( pix->height % MAPSPRITE_SIZE ) + h = pix->height - ( pix->height % MAPSPRITE_SIZE ); + else h = pix->height; + + if( w < MAPSPRITE_SIZE ) w = MAPSPRITE_SIZE; + if( h < MAPSPRITE_SIZE ) h = MAPSPRITE_SIZE; + + // resample image if needed + gEngfuncs.Image_Process( &pix, w, h, IMAGE_FORCE_RGBA|IMAGE_RESAMPLE, 0.0f ); + + w = h = MAPSPRITE_SIZE; + + // check range + if( w > pix->width ) w = pix->width; + if( h > pix->height ) h = pix->height; + + // determine how many frames we needs + numframes = (pix->width * pix->height) / (w * h); + mod->mempool = Mem_AllocPool( va( "^2%s^7", mod->name )); + psprite = Mem_Calloc( mod->mempool, sizeof( msprite_t ) + ( numframes - 1 ) * sizeof( psprite->frames )); + mod->cache.data = psprite; // make link to extradata + + psprite->type = SPR_FWD_PARALLEL_ORIENTED; + psprite->texFormat = SPR_ALPHTEST; + psprite->numframes = mod->numframes = numframes; + psprite->radius = sqrt(((w >> 1) * (w >> 1)) + ((h >> 1) * (h >> 1))); + + mod->mins[0] = mod->mins[1] = -w / 2; + mod->maxs[0] = mod->maxs[1] = w / 2; + mod->mins[2] = -h / 2; + mod->maxs[2] = h / 2; + + // create a temporary pic + memset( &temp, 0, sizeof( temp )); + temp.width = w; + temp.height = h; + temp.type = pix->type; + temp.flags = pix->flags; + temp.size = w * h * gEngfuncs.Image_GetPFDesc(temp.type)->bpp; + temp.buffer = Mem_Malloc( r_temppool, temp.size ); + temp.palette = NULL; + + // chop the image and upload into video memory + for( i = xl = yl = 0; i < numframes; i++ ) + { + xh = xl + w; + yh = yl + h; + + src = pix->buffer + ( yl * pix->width + xl ) * 4; + linedelta = ( pix->width - w ) * 4; + dst = temp.buffer; + + // cut block from source + for( y = yl; y < yh; y++ ) + { + for( x = xl; x < xh; x++ ) + for( j = 0; j < 4; j++ ) + *dst++ = *src++; + src += linedelta; + } + + // build uinque frame name + Q_snprintf( texname, sizeof( texname ), "#MAP/%s_%i%i.spr", mod->name, i / 10, i % 10 ); + + psprite->frames[i].frameptr = Mem_Calloc( mod->mempool, sizeof( mspriteframe_t )); + pspriteframe = psprite->frames[i].frameptr; + pspriteframe->width = w; + pspriteframe->height = h; + pspriteframe->up = ( h >> 1 ); + pspriteframe->left = -( w >> 1 ); + pspriteframe->down = ( h >> 1 ) - h; + pspriteframe->right = w + -( w >> 1 ); + pspriteframe->gl_texturenum = GL_LoadTextureInternal( texname, &temp, TF_IMAGE ); + + xl += w; + if( xl >= pix->width ) + { + xl = 0; + yl += h; + } + } + + gEngfuncs.FS_FreeImage( pix ); + Mem_Free( temp.buffer ); + + if( loaded ) *loaded = true; +} + +/* +==================== +Mod_UnloadSpriteModel + +release sprite model and frames +==================== +*/ +void Mod_SpriteUnloadTextures( void *data ) +{ + msprite_t *psprite; + mspritegroup_t *pspritegroup; + mspriteframe_t *pspriteframe; + int i, j; + + psprite = data; + + if( psprite ) + { + // release all textures + for( i = 0; i < psprite->numframes; i++ ) + { + if( psprite->frames[i].type == SPR_SINGLE ) + { + pspriteframe = psprite->frames[i].frameptr; + GL_FreeTexture( pspriteframe->gl_texturenum ); + } + else + { + pspritegroup = (mspritegroup_t *)psprite->frames[i].frameptr; + + for( j = 0; j < pspritegroup->numframes; j++ ) + { + pspriteframe = pspritegroup->frames[i]; + GL_FreeTexture( pspriteframe->gl_texturenum ); + } + } + } + } +} + +/* +================ +R_GetSpriteFrame + +assume pModel is valid +================ +*/ +mspriteframe_t *R_GetSpriteFrame( const model_t *pModel, int frame, float yaw ) +{ + msprite_t *psprite; + mspritegroup_t *pspritegroup; + mspriteframe_t *pspriteframe = NULL; + float *pintervals, fullinterval; + int i, numframes; + float targettime; + + Assert( pModel != NULL ); + psprite = pModel->cache.data; + + if( frame < 0 ) + { + frame = 0; + } + else if( frame >= psprite->numframes ) + { + if( frame > psprite->numframes ) + gEngfuncs.Con_Printf( S_WARN "R_GetSpriteFrame: no such frame %d (%s)\n", frame, pModel->name ); + frame = psprite->numframes - 1; + } + + if( psprite->frames[frame].type == SPR_SINGLE ) + { + pspriteframe = psprite->frames[frame].frameptr; + } + else if( psprite->frames[frame].type == SPR_GROUP ) + { + pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; + pintervals = pspritegroup->intervals; + numframes = pspritegroup->numframes; + fullinterval = pintervals[numframes-1]; + + // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values + // are positive, so we don't have to worry about division by zero + targettime = gpGlobals->time - ((int)( gpGlobals->time / fullinterval )) * fullinterval; + + for( i = 0; i < (numframes - 1); i++ ) + { + if( pintervals[i] > targettime ) + break; + } + pspriteframe = pspritegroup->frames[i]; + } + else if( psprite->frames[frame].type == FRAME_ANGLED ) + { + int angleframe = (int)(Q_rint(( RI.viewangles[1] - yaw + 45.0f ) / 360 * 8) - 4) & 7; + + // e.g. doom-style sprite monsters + pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; + pspriteframe = pspritegroup->frames[angleframe]; + } + + return pspriteframe; +} + +/* +================ +R_GetSpriteFrameInterpolant + +NOTE: we using prevblending[0] and [1] for holds interval +between frames where are we lerping +================ +*/ +float R_GetSpriteFrameInterpolant( cl_entity_t *ent, mspriteframe_t **oldframe, mspriteframe_t **curframe ) +{ + msprite_t *psprite; + mspritegroup_t *pspritegroup; + int i, j, numframes, frame; + float lerpFrac, time, jtime, jinterval; + float *pintervals, fullinterval, targettime; + int m_fDoInterp; + + psprite = ent->model->cache.data; + frame = (int)ent->curstate.frame; + lerpFrac = 1.0f; + + // misc info + m_fDoInterp = (ent->curstate.effects & EF_NOINTERP) ? false : true; + + if( frame < 0 ) + { + frame = 0; + } + else if( frame >= psprite->numframes ) + { + gEngfuncs.Con_Reportf( S_WARN "R_GetSpriteFrameInterpolant: no such frame %d (%s)\n", frame, ent->model->name ); + frame = psprite->numframes - 1; + } + + if( psprite->frames[frame].type == FRAME_SINGLE ) + { + if( m_fDoInterp ) + { + if( ent->latched.prevblending[0] >= psprite->numframes || psprite->frames[ent->latched.prevblending[0]].type != FRAME_SINGLE ) + { + // this can be happens when rendering switched between single and angled frames + // or change model on replace delta-entity + ent->latched.prevblending[0] = ent->latched.prevblending[1] = frame; + ent->latched.sequencetime = gpGlobals->time; + lerpFrac = 1.0f; + } + + if( ent->latched.sequencetime < gpGlobals->time ) + { + if( frame != ent->latched.prevblending[1] ) + { + ent->latched.prevblending[0] = ent->latched.prevblending[1]; + ent->latched.prevblending[1] = frame; + ent->latched.sequencetime = gpGlobals->time; + lerpFrac = 0.0f; + } + else lerpFrac = (gpGlobals->time - ent->latched.sequencetime) * 11.0f; + } + else + { + ent->latched.prevblending[0] = ent->latched.prevblending[1] = frame; + ent->latched.sequencetime = gpGlobals->time; + lerpFrac = 0.0f; + } + } + else + { + ent->latched.prevblending[0] = ent->latched.prevblending[1] = frame; + lerpFrac = 1.0f; + } + + if( ent->latched.prevblending[0] >= psprite->numframes ) + { + // reset interpolation on change model + ent->latched.prevblending[0] = ent->latched.prevblending[1] = frame; + ent->latched.sequencetime = gpGlobals->time; + lerpFrac = 0.0f; + } + + // get the interpolated frames + if( oldframe ) *oldframe = psprite->frames[ent->latched.prevblending[0]].frameptr; + if( curframe ) *curframe = psprite->frames[frame].frameptr; + } + else if( psprite->frames[frame].type == FRAME_GROUP ) + { + pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; + pintervals = pspritegroup->intervals; + numframes = pspritegroup->numframes; + fullinterval = pintervals[numframes-1]; + jinterval = pintervals[1] - pintervals[0]; + time = gpGlobals->time; + jtime = 0.0f; + + // when loading in Mod_LoadSpriteGroup, we guaranteed all interval values + // are positive, so we don't have to worry about division by zero + targettime = time - ((int)(time / fullinterval)) * fullinterval; + + // LordHavoc: since I can't measure the time properly when it loops from numframes - 1 to 0, + // i instead measure the time of the first frame, hoping it is consistent + for( i = 0, j = numframes - 1; i < (numframes - 1); i++ ) + { + if( pintervals[i] > targettime ) + break; + j = i; + jinterval = pintervals[i] - jtime; + jtime = pintervals[i]; + } + + if( m_fDoInterp ) + lerpFrac = (targettime - jtime) / jinterval; + else j = i; // no lerping + + // get the interpolated frames + if( oldframe ) *oldframe = pspritegroup->frames[j]; + if( curframe ) *curframe = pspritegroup->frames[i]; + } + else if( psprite->frames[frame].type == FRAME_ANGLED ) + { + // e.g. doom-style sprite monsters + float yaw = ent->angles[YAW]; + int angleframe = (int)(Q_rint(( RI.viewangles[1] - yaw + 45.0f ) / 360 * 8) - 4) & 7; + + if( m_fDoInterp ) + { + if( ent->latched.prevblending[0] >= psprite->numframes || psprite->frames[ent->latched.prevblending[0]].type != FRAME_ANGLED ) + { + // this can be happens when rendering switched between single and angled frames + // or change model on replace delta-entity + ent->latched.prevblending[0] = ent->latched.prevblending[1] = frame; + ent->latched.sequencetime = gpGlobals->time; + lerpFrac = 1.0f; + } + + if( ent->latched.sequencetime < gpGlobals->time ) + { + if( frame != ent->latched.prevblending[1] ) + { + ent->latched.prevblending[0] = ent->latched.prevblending[1]; + ent->latched.prevblending[1] = frame; + ent->latched.sequencetime = gpGlobals->time; + lerpFrac = 0.0f; + } + else lerpFrac = (gpGlobals->time - ent->latched.sequencetime) * ent->curstate.framerate; + } + else + { + ent->latched.prevblending[0] = ent->latched.prevblending[1] = frame; + ent->latched.sequencetime = gpGlobals->time; + lerpFrac = 0.0f; + } + } + else + { + ent->latched.prevblending[0] = ent->latched.prevblending[1] = frame; + lerpFrac = 1.0f; + } + + pspritegroup = (mspritegroup_t *)psprite->frames[ent->latched.prevblending[0]].frameptr; + if( oldframe ) *oldframe = pspritegroup->frames[angleframe]; + + pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; + if( curframe ) *curframe = pspritegroup->frames[angleframe]; + } + + return lerpFrac; +} + +/* +================ +R_CullSpriteModel + +Cull sprite model by bbox +================ +*/ +qboolean R_CullSpriteModel( cl_entity_t *e, vec3_t origin ) +{ + vec3_t sprite_mins, sprite_maxs; + float scale = 1.0f; + + if( !e->model->cache.data ) + return true; + + if( e->curstate.scale > 0.0f ) + scale = e->curstate.scale; + + // scale original bbox (no rotation for sprites) + VectorScale( e->model->mins, scale, sprite_mins ); + VectorScale( e->model->maxs, scale, sprite_maxs ); + + sprite_radius = RadiusFromBounds( sprite_mins, sprite_maxs ); + + VectorAdd( sprite_mins, origin, sprite_mins ); + VectorAdd( sprite_maxs, origin, sprite_maxs ); + + return R_CullModel( e, sprite_mins, sprite_maxs ); +} + +/* +================ +R_GlowSightDistance + +Set sprite brightness factor +================ +*/ +static float R_SpriteGlowBlend( vec3_t origin, int rendermode, int renderfx, float *pscale ) +{ + float dist, brightness; + vec3_t glowDist; + pmtrace_t *tr; + + VectorSubtract( origin, RI.vieworg, glowDist ); + dist = VectorLength( glowDist ); + + if( RP_NORMALPASS( )) + { + tr = gEngfuncs.EV_VisTraceLine( RI.vieworg, origin, r_traceglow->value ? PM_GLASS_IGNORE : (PM_GLASS_IGNORE|PM_STUDIO_IGNORE)); + + if(( 1.0f - tr->fraction ) * dist > 8.0f ) + return 0.0f; + } + + if( renderfx == kRenderFxNoDissipation ) + return 1.0f; + + brightness = GLARE_FALLOFF / ( dist * dist ); + brightness = bound( 0.05f, brightness, 1.0f ); + *pscale *= dist * ( 1.0f / 200.0f ); + + return brightness; +} + +/* +================ +R_SpriteOccluded + +Do occlusion test for glow-sprites +================ +*/ +qboolean R_SpriteOccluded( cl_entity_t *e, vec3_t origin, float *pscale ) +{ + if( e->curstate.rendermode == kRenderGlow ) + { + float blend; + vec3_t v; + + TriWorldToScreen( origin, v ); + + if( v[0] < RI.viewport[0] || v[0] > RI.viewport[0] + RI.viewport[2] ) + return true; // do scissor + if( v[1] < RI.viewport[1] || v[1] > RI.viewport[1] + RI.viewport[3] ) + return true; // do scissor + + blend = R_SpriteGlowBlend( origin, e->curstate.rendermode, e->curstate.renderfx, pscale ); + tr.blend *= blend; + + if( blend <= 0.01f ) + return true; // faded + } + else + { + if( R_CullSpriteModel( e, origin )) + return true; + } + + return false; +} + +/* +================= +R_DrawSpriteQuad +================= +*/ +static void R_DrawSpriteQuad( mspriteframe_t *frame, vec3_t org, vec3_t v_right, vec3_t v_up, float scale ) +{ + vec3_t point; + image_t *image; + + r_stats.c_sprite_polys++; + image = R_GetTexture(frame->gl_texturenum); + r_affinetridesc.pskin = image->pixels[0]; + r_affinetridesc.skinwidth = image->width; + r_affinetridesc.skinheight = image->height; + + TriBegin( TRI_QUADS ); + TriTexCoord2f( 0.0f, 1.0f ); + VectorMA( org, frame->down * scale, v_up, point ); + VectorMA( point, frame->left * scale, v_right, point ); + TriVertex3fv( point ); + TriTexCoord2f( 0.0f, 0.0f ); + VectorMA( org, frame->up * scale, v_up, point ); + VectorMA( point, frame->left * scale, v_right, point ); + TriVertex3fv( point ); + TriTexCoord2f( 1.0f, 0.0f ); + VectorMA( org, frame->up * scale, v_up, point ); + VectorMA( point, frame->right * scale, v_right, point ); + TriVertex3fv( point ); + TriTexCoord2f( 1.0f, 1.0f ); + VectorMA( org, frame->down * scale, v_up, point ); + VectorMA( point, frame->right * scale, v_right, point ); + TriVertex3fv( point ); + TriEnd(); + +#if 0 + image_t *pic = R_GetTexture(frame->gl_texturenum); + r_polydesc.pixels = pic->pixels[0]; + r_polydesc.pixel_width = pic->width; + r_polydesc.pixel_height = pic->height; + r_polydesc.dist = 0; + + // generate the sprite's axes, completely parallel to the viewplane. + VectorCopy (v_up, r_polydesc.vup); + VectorCopy (v_right, r_polydesc.vright); + VectorCopy (vpn, r_polydesc.vpn); + +// build the sprite poster in worldspace + VectorScale (r_polydesc.vright, + frame->width - frame->origin_x, right); + VectorScale (r_polydesc.vup, + s_psprframe->height - s_psprframe->origin_y, up); + VectorScale (r_polydesc.vright, + -s_psprframe->origin_x, left); + VectorScale (r_polydesc.vup, + -s_psprframe->origin_y, down); + + // invert UP vector for sprites + VectorInverse( r_polydesc.vup ); + + pverts = r_clip_verts[0]; + + pverts[0][0] = r_entorigin[0] + up[0] + left[0]; + pverts[0][1] = r_entorigin[1] + up[1] + left[1]; + pverts[0][2] = r_entorigin[2] + up[2] + left[2]; + pverts[0][3] = 0; + pverts[0][4] = 0; + + pverts[1][0] = r_entorigin[0] + up[0] + right[0]; + pverts[1][1] = r_entorigin[1] + up[1] + right[1]; + pverts[1][2] = r_entorigin[2] + up[2] + right[2]; + pverts[1][3] = s_psprframe->width; + pverts[1][4] = 0; + + pverts[2][0] = r_entorigin[0] + down[0] + right[0]; + pverts[2][1] = r_entorigin[1] + down[1] + right[1]; + pverts[2][2] = r_entorigin[2] + down[2] + right[2]; + pverts[2][3] = s_psprframe->width; + pverts[2][4] = s_psprframe->height; + + pverts[3][0] = r_entorigin[0] + down[0] + left[0]; + pverts[3][1] = r_entorigin[1] + down[1] + left[1]; + pverts[3][2] = r_entorigin[2] + down[2] + left[2]; + pverts[3][3] = 0; + pverts[3][4] = s_psprframe->height; + + r_polydesc.nump = 4; + r_polydesc.s_offset = ( r_polydesc.pixel_width >> 1); + r_polydesc.t_offset = ( r_polydesc.pixel_height >> 1); + VectorCopy( modelorg, r_polydesc.viewer_position ); + + r_polydesc.stipple_parity = 1; + if ( currententity->flags & RF_TRANSLUCENT ) + R_ClipAndDrawPoly ( currententity->alpha, false, true ); + else + R_ClipAndDrawPoly ( 1.0F, false, true ); + r_polydesc.stipple_parity = 0; +#endif +} + +static qboolean R_SpriteHasLightmap( cl_entity_t *e, int texFormat ) +{ + if( !r_sprite_lighting->value ) + return false; + + if( texFormat != SPR_ALPHTEST ) + return false; + + if( e->curstate.effects & EF_FULLBRIGHT ) + return false; + + if( e->curstate.renderamt <= 127 ) + return false; + + switch( e->curstate.rendermode ) + { + case kRenderNormal: + case kRenderTransAlpha: + case kRenderTransTexture: + break; + default: + return false; + } + + return true; +} + +/* +================= +R_SpriteAllowLerping +================= +*/ +static qboolean R_SpriteAllowLerping( cl_entity_t *e, msprite_t *psprite ) +{ + if( !r_sprite_lerping->value ) + return false; + + if( psprite->numframes <= 1 ) + return false; + + if( psprite->texFormat != SPR_ADDITIVE ) + return false; + + if( e->curstate.rendermode == kRenderNormal || e->curstate.rendermode == kRenderTransAlpha ) + return false; + + return true; +} + +/* +================= +R_DrawSpriteModel +================= +*/ +void R_DrawSpriteModel( cl_entity_t *e ) +{ + mspriteframe_t *frame, *oldframe; + msprite_t *psprite; + model_t *model; + int i, type; + float angle, dot, sr, cr; + float lerp = 1.0f, ilerp, scale; + vec3_t v_forward, v_right, v_up; + vec3_t origin, color, color2; + + if( RI.params & RP_ENVVIEW ) + return; + + model = e->model; + psprite = (msprite_t * )model->cache.data; + VectorCopy( e->origin, origin ); // set render origin + + // do movewith + if( e->curstate.aiment > 0 && e->curstate.movetype == MOVETYPE_FOLLOW ) + { + cl_entity_t *parent; + + parent = gEngfuncs.GetEntityByIndex( e->curstate.aiment ); + + if( parent && parent->model ) + { + if( parent->model->type == mod_studio && e->curstate.body > 0 ) + { + int num = bound( 1, e->curstate.body, MAXSTUDIOATTACHMENTS ); + VectorCopy( parent->attachment[num-1], origin ); + } + else VectorCopy( parent->origin, origin ); + } + } + + scale = e->curstate.scale; + if( !scale ) scale = 1.0f; + + if( R_SpriteOccluded( e, origin, &scale )) + return; // sprite culled + + r_stats.c_sprite_models_drawn++; + + if( e->curstate.rendermode == kRenderGlow || e->curstate.rendermode == kRenderTransAdd ) + R_AllowFog( false ); +#if 0 + // select properly rendermode + switch( e->curstate.rendermode ) + { + case kRenderTransAlpha: + pglDepthMask( GL_FALSE ); + case kRenderTransColor: + case kRenderTransTexture: + pglEnable( GL_BLEND ); + pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + break; + case kRenderGlow: + pglDisable( GL_DEPTH_TEST ); + case kRenderTransAdd: + pglEnable( GL_BLEND ); + pglBlendFunc( GL_SRC_ALPHA, GL_ONE ); + pglDepthMask( GL_FALSE ); + break; + case kRenderNormal: + default: + pglDisable( GL_BLEND ); + break; + } + + // all sprites can have color + pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + pglEnable( GL_ALPHA_TEST ); +#endif + // NOTE: never pass sprites with rendercolor '0 0 0' it's a stupid Valve Hammer Editor bug + if( e->curstate.rendercolor.r || e->curstate.rendercolor.g || e->curstate.rendercolor.b ) + { + color[0] = (float)e->curstate.rendercolor.r * ( 1.0f / 255.0f ); + color[1] = (float)e->curstate.rendercolor.g * ( 1.0f / 255.0f ); + color[2] = (float)e->curstate.rendercolor.b * ( 1.0f / 255.0f ); + } + else + { + color[0] = 1.0f; + color[1] = 1.0f; + color[2] = 1.0f; + } + + if( R_SpriteHasLightmap( e, psprite->texFormat )) + { + colorVec lightColor = R_LightPoint( origin ); + // FIXME: collect light from dlights? + color2[0] = (float)lightColor.r * ( 1.0f / 255.0f ); + color2[1] = (float)lightColor.g * ( 1.0f / 255.0f ); + color2[2] = (float)lightColor.b * ( 1.0f / 255.0f ); + // NOTE: sprites with 'lightmap' looks ugly when alpha func is GL_GREATER 0.0 + // pglAlphaFunc( GL_GREATER, 0.5f ); + } + + if( R_SpriteAllowLerping( e, psprite )) + lerp = R_GetSpriteFrameInterpolant( e, &oldframe, &frame ); + else frame = oldframe = R_GetSpriteFrame( model, e->curstate.frame, e->angles[YAW] ); + + type = psprite->type; + + // automatically roll parallel sprites if requested + if( e->angles[ROLL] != 0.0f && type == SPR_FWD_PARALLEL ) + type = SPR_FWD_PARALLEL_ORIENTED; + + switch( type ) + { + case SPR_ORIENTED: + AngleVectors( e->angles, v_forward, v_right, v_up ); + VectorScale( v_forward, 0.01f, v_forward ); // to avoid z-fighting + VectorSubtract( origin, v_forward, origin ); + break; + case SPR_FACING_UPRIGHT: + VectorSet( v_right, origin[1] - RI.vieworg[1], -(origin[0] - RI.vieworg[0]), 0.0f ); + VectorSet( v_up, 0.0f, 0.0f, 1.0f ); + VectorNormalize( v_right ); + break; + case SPR_FWD_PARALLEL_UPRIGHT: + dot = RI.vforward[2]; + if(( dot > 0.999848f ) || ( dot < -0.999848f )) // cos(1 degree) = 0.999848 + return; // invisible + VectorSet( v_up, 0.0f, 0.0f, 1.0f ); + VectorSet( v_right, RI.vforward[1], -RI.vforward[0], 0.0f ); + VectorNormalize( v_right ); + break; + case SPR_FWD_PARALLEL_ORIENTED: + angle = e->angles[ROLL] * (M_PI2 / 360.0f); + SinCos( angle, &sr, &cr ); + for( i = 0; i < 3; i++ ) + { + v_right[i] = (RI.vright[i] * cr + RI.vup[i] * sr); + v_up[i] = RI.vright[i] * -sr + RI.vup[i] * cr; + } + break; + case SPR_FWD_PARALLEL: // normal sprite + default: + VectorCopy( RI.vright, v_right ); + VectorCopy( RI.vup, v_up ); + break; + } + + //if( psprite->facecull == SPR_CULL_NONE ) + //GL_Cull( GL_NONE ); + + if( oldframe == frame ) + { + // draw the single non-lerped frame + _TriColor4f( color[0], color[1], color[2], tr.blend ); + GL_Bind( XASH_TEXTURE0, frame->gl_texturenum ); + R_DrawSpriteQuad( frame, origin, v_right, v_up, scale ); + } + else + { + // draw two combined lerped frames + lerp = bound( 0.0f, lerp, 1.0f ); + ilerp = 1.0f - lerp; + + if( ilerp != 0.0f ) + { + _TriColor4f( color[0], color[1], color[2], tr.blend * ilerp ); + GL_Bind( XASH_TEXTURE0, oldframe->gl_texturenum ); + R_DrawSpriteQuad( oldframe, origin, v_right, v_up, scale ); + } + + if( lerp != 0.0f ) + { + _TriColor4f( color[0], color[1], color[2], tr.blend * lerp ); + GL_Bind( XASH_TEXTURE0, frame->gl_texturenum ); + R_DrawSpriteQuad( frame, origin, v_right, v_up, scale ); + } + } +#if 0 + // draw the sprite 'lightmap' :-) + if( R_SpriteHasLightmap( e, psprite->texFormat )) + { + if( !r_lightmap->value ) + pglEnable( GL_BLEND ); + else pglDisable( GL_BLEND ); + pglDepthFunc( GL_EQUAL ); + pglDisable( GL_ALPHA_TEST ); + pglBlendFunc( GL_ZERO, GL_SRC_COLOR ); + pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); + + pglColor4f( color2[0], color2[1], color2[2], tr.blend ); + GL_Bind( XASH_TEXTURE0, tr.whiteTexture ); + R_DrawSpriteQuad( frame, origin, v_right, v_up, scale ); + pglAlphaFunc( GL_GREATER, DEFAULT_ALPHATEST ); + pglDepthFunc( GL_LEQUAL ); + } + + if( psprite->facecull == SPR_CULL_NONE ) + GL_Cull( GL_FRONT ); + + pglDisable( GL_ALPHA_TEST ); + pglDepthMask( GL_TRUE ); + + if( e->curstate.rendermode == kRenderGlow || e->curstate.rendermode == kRenderTransAdd ) + R_AllowFog( true ); + + if( e->curstate.rendermode != kRenderNormal ) + { + pglDisable( GL_BLEND ); + pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); + pglEnable( GL_DEPTH_TEST ); + } +#endif +} diff --git a/r_triapi.c b/r_triapi.c index e6c3193b..7491ec16 100644 --- a/r_triapi.c +++ b/r_triapi.c @@ -116,6 +116,8 @@ void TriBegin( int mode1 ) pglBegin( mode ); #endif + if( mode1 == TRI_QUADS ) + mode1 = TRI_TRIANGLE_FAN; mode = mode1; vertcount = n = vertcount = 0; } @@ -242,6 +244,17 @@ TriVertex3f */ void TriVertex3f( float x, float y, float z ) { + if( mode == TRI_TRIANGLES ) + { + R_SetupFinalVert( &triv[vertcount], x, y, z, light << 8,s,t); + vertcount++; + if( vertcount == 3 ) + { + R_RenderTriangle( &triv[0], &triv[1], &triv[2] ); + R_RenderTriangle( &triv[2], &triv[1], &triv[0] ); + vertcount = 0; + } + } if( mode == TRI_TRIANGLE_FAN ) { R_SetupFinalVert( &triv[vertcount], x, y, z, light << 8,s,t); @@ -300,7 +313,7 @@ TriWorldToScreen convert world coordinates (x,y,z) into screen (x, y) ============= */ -int TriWorldToScreen( float *world, float *screen ) +int TriWorldToScreen( const float *world, float *screen ) { int retval; From 0c62967d8a1498654a9bc43b93df88feb71565a4 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 30 Mar 2019 21:04:14 +0700 Subject: [PATCH 046/115] ref_soft: re-enable lightstyles for LightPoint --- r_light.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/r_light.c b/r_light.c index 8f0e2331..413004c2 100644 --- a/r_light.c +++ b/r_light.c @@ -346,9 +346,9 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f, if( 1 ) //tr.ignore_lightgamma ) { - cv->r += lm->r * 255 * 2.5; // scale; - cv->g += lm->g * 255 * 2.5; // scale; - cv->b += lm->b * 255 * 2.5; // scale; + cv->r += lm->r * scale * 2.5; // scale; + cv->g += lm->g * scale * 2.5; // scale; + cv->b += lm->b * scale * 2.5; // scale; } else { From c52d4b79981f29efa3453c882c3e72e68d88ea19 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 30 Mar 2019 21:16:14 +0700 Subject: [PATCH 047/115] ref_soft: Restore lightmap gamma calculation --- r_light.c | 2 +- r_main.c | 8 +++++--- r_surf.c | 8 ++++---- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/r_light.c b/r_light.c index 413004c2..010e594b 100644 --- a/r_light.c +++ b/r_light.c @@ -344,7 +344,7 @@ static qboolean R_RecursiveLightPoint( model_t *model, mnode_t *node, float p1f, { uint scale = tr.lightstylevalue[surf->styles[map]]; - if( 1 ) //tr.ignore_lightgamma ) + if( tr.ignore_lightgamma ) { cv->r += lm->r * scale * 2.5; // scale; cv->g += lm->g * scale * 2.5; // scale; diff --git a/r_main.c b/r_main.c index 6283efae..3eb85cfb 100644 --- a/r_main.c +++ b/r_main.c @@ -1734,16 +1734,18 @@ void R_BeginFrame( qboolean clearScene ) // glConfig.softwareGammaUpdate = true; // GL_RebuildLightmaps(); // glConfig.softwareGammaUpdate = false; + D_FlushCaches( false ); // next frame will be restored gamma - // SetBits( vid_brightness->flags, FCVAR_CHANGED ); - // SetBits( vid_gamma->flags, FCVAR_CHANGED ); + SetBits( vid_brightness->flags, FCVAR_CHANGED ); + SetBits( vid_gamma->flags, FCVAR_CHANGED ); } else if( FBitSet( vid_gamma->flags, FCVAR_CHANGED ) || FBitSet( vid_brightness->flags, FCVAR_CHANGED )) { - // gEngfuncs.BuildGammaTable( vid_gamma->value, vid_brightness->value ); + gEngfuncs.BuildGammaTable( vid_gamma->value, vid_brightness->value ); //glConfig.softwareGammaUpdate = true; // GL_RebuildLightmaps(); + D_FlushCaches( false ); //glConfig.softwareGammaUpdate = false; } diff --git a/r_surf.c b/r_surf.c index 0907fe34..9081b83a 100644 --- a/r_surf.c +++ b/r_surf.c @@ -149,7 +149,7 @@ void R_AddDynamicLights( msurface_t *surf ) { //printf("dlight %f\n", dist); //*(void**)0 = 0; - bl[0] += ((int)((rad - dist) * 256) * 7.5); + bl[0] += ((int)((rad - dist) * 256) * gEngfuncs.LightToTexGamma( (dl->color.r + dl->color.g + dl->color.b ) / 3) * 3) / 256; //bl[1] += ((int)((rad - dist) * 256) * 2.5) / 256; //bl[2] += ((int)((rad - dist) * 256) * 2.5) / 256; } @@ -206,9 +206,9 @@ static void R_BuildLightMap( ) for( i = 0, bl = blocklights; i < size; i++, bl += 1, lm++ ) { - bl[0] += lm->r * scale * 2.5; - bl[0] += lm->g * scale * 2.5; - bl[0] += lm->b * scale * 2.5; + bl[0] += gEngfuncs.LightToTexGamma( lm->r ) * scale; + bl[0] += gEngfuncs.LightToTexGamma( lm->g ) * scale; + bl[0] += gEngfuncs.LightToTexGamma( lm->b ) * scale; //printf("test\n"); //bl[1] += gEngfuncs.LightToTexGamma( lm->g ) * scale; From 25860f6263d24b15cfcec87ea0b3cdd32d9a6a82 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sun, 31 Mar 2019 02:05:08 +0700 Subject: [PATCH 048/115] ref_soft: remove some unused globals --- r_edge.c | 4 +- r_local.h | 26 +++------- r_main.c | 27 ++++------- r_misc.c | 26 +++++----- r_poly.c | 4 +- r_polyse.c | 134 --------------------------------------------------- r_scan.c | 2 +- r_surf.c | 2 +- r_trialias.c | 16 ------ 9 files changed, 34 insertions(+), 207 deletions(-) diff --git a/r_edge.c b/r_edge.c index c5b4b006..490204f6 100644 --- a/r_edge.c +++ b/r_edge.c @@ -73,7 +73,7 @@ edge_t edge_tail; edge_t edge_aftertail; edge_t edge_sentinel; -float fv; +static float fv; static int miplevel; @@ -1128,7 +1128,7 @@ void D_DrawSurfaces (void) if (!s->spans) continue; - r_drawnpolycount++; + //r_drawnpolycount++; #if 1 if(s->flags & SURF_DRAWSKY) D_BackgroundSurf (s); diff --git a/r_local.h b/r_local.h index 546b6b79..72e7a57c 100644 --- a/r_local.h +++ b/r_local.h @@ -333,7 +333,6 @@ extern ref_speeds_t r_stats; extern ref_instance_t RI; extern gl_globals_t tr; -extern float gldepthmin, gldepthmax; #define r_numEntities (tr.draw_list->num_solid_entities + tr.draw_list->num_trans_entities) #define r_numStatics (r_stats.c_client_ents) @@ -1082,7 +1081,7 @@ VARS ==================================================== */ -extern int d_spanpixcount; +//extern int d_spanpixcount; extern int r_framecount; // sequence # of current frame since Quake // started extern float r_aliasuvscale; // scale-up factor for screen u and v @@ -1109,7 +1108,7 @@ extern drawsurf_t r_drawsurf; void R_DrawSurface (void); -extern int c_surf; +//extern int c_surf; extern byte r_warpbuffer[WARP_WIDTH * WARP_HEIGHT]; @@ -1137,9 +1136,6 @@ void NonTurbulent8 (espan_t *pspan); //PGM surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel); -extern int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle; - -extern int d_pix_min, d_pix_max, d_pix_shift; extern pixel_t *d_viewbuffer; extern short *d_pzbuffer; @@ -1156,7 +1152,6 @@ extern int cachewidth; extern pixel_t *cacheblock; extern int r_screenwidth; -extern int r_drawnpolycount; extern int sintable[1280]; extern int intsintable[1280]; @@ -1176,13 +1171,13 @@ extern surf_t *surfaces, *surface_p, *surf_max; //=================================================================== -extern vec3_t sxformaxis[4]; // s axis transformed into viewspace -extern vec3_t txformaxis[4]; // t axis transformed into viewspac +//extern vec3_t sxformaxis[4]; // s axis transformed into viewspace +//extern vec3_t txformaxis[4]; // t axis transformed into viewspac extern float xcenter, ycenter; extern float xscale, yscale; extern float xscaleinv, yscaleinv; -extern float xscaleshrink, yscaleshrink; +//extern float xscaleshrink, yscaleshrink; extern edge_t *auxedges; @@ -1199,7 +1194,6 @@ extern edge_t edge_aftertail; extern int r_frustum_indexes[4*6]; -extern int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs; extern qboolean r_surfsonstack; extern mleaf_t *r_viewleaf; @@ -1207,7 +1201,7 @@ extern int r_viewcluster, r_oldviewcluster; extern int r_clipflags; extern int r_dlightframecount; -extern qboolean r_fov_greater_than_90; +//extern qboolean r_fov_greater_than_90; extern cvar_t *sw_aliasstats; @@ -1244,16 +1238,10 @@ extern mplane_t screenedge[4]; extern clipplane_t view_clipplanes[4]; extern int *pfrustum_indexes[4]; -extern vec3_t vup, base_vup; -extern vec3_t vpn, base_vpn; -extern vec3_t vright, base_vright; - extern cvar_t *r_fullbright; #define CACHESPOT(surf) ((surfcache_t**)surf->info->reserved) extern int r_visframecount; -extern mvertex_t *r_pcurrentvertbase; -extern int r_maxvalidedgeoffset; extern int r_currentkey; extern int r_currentbkey; extern qboolean insubmodel; @@ -1267,7 +1255,7 @@ extern int ubasestep, errorterm, erroradjustup, erroradjustdown; extern mvertex_t *r_pcurrentvertbase; -extern int r_maxvalidedgeoffset; +//extern int r_maxvalidedgeoffset; typedef struct { diff --git a/r_main.c b/r_main.c index 3eb85cfb..5776d688 100644 --- a/r_main.c +++ b/r_main.c @@ -20,10 +20,9 @@ GNU General Public License for more details. //#include "particledef.h" #include "entity_types.h" #include "mod_local.h" - +int r_cnumsurfs; #define IsLiquidContents( cnt ) ( cnt == CONTENTS_WATER || cnt == CONTENTS_SLIME || cnt == CONTENTS_LAVA ) -float gldepthmin, gldepthmax; ref_instance_t RI; @@ -42,7 +41,7 @@ vec3_t r_origin; float xcenter, ycenter; float xscale, yscale; float xscaleinv, yscaleinv; -float xscaleshrink, yscaleshrink; +//float xscaleshrink, yscaleshrink; float aliasxscale, aliasyscale, aliasxcenter, aliasycenter; int r_screenwidth; @@ -58,10 +57,10 @@ mplane_t screenedge[4]; // int r_framecount = 1; // so frame counts initialized to 0 don't match int r_visframecount; -int d_spanpixcount; -int r_polycount; -int r_drawnpolycount; -int r_wholepolycount; +//int d_spanpixcount; +//int r_polycount; +//int r_drawnpolycount; +//int r_wholepolycount; int *pfrustum_indexes[4]; int r_frustum_indexes[4*6]; @@ -113,8 +112,6 @@ cvar_t *sw_lockpvs; cvar_t *r_decals; - -mleaf_t *r_viewleaf; int r_viewcluster, r_oldviewcluster; float d_sdivzstepu, d_tdivzstepu, d_zistepu; @@ -134,8 +131,7 @@ qboolean r_dowarp; mvertex_t *r_pcurrentvertbase; -int c_surf; -int r_maxsurfsseen, r_maxedgesseen, r_cnumsurfs; +//int c_surf; qboolean r_surfsonstack; int r_clipflags; byte r_warpbuffer[WARP_WIDTH * WARP_HEIGHT]; @@ -1032,8 +1028,8 @@ R_DrawEntitiesOnList void R_DrawEntitiesOnList( void ) { int i; - extern int d_aflatcolor; - d_aflatcolor = 0; + //extern int d_aflatcolor; + //d_aflatcolor = 0; tr.blend = 1.0f; // GL_CheckForErrors(); //RI.currententity = gEngfuncs.GetEntityByIndex(0); @@ -1047,7 +1043,7 @@ void R_DrawEntitiesOnList( void ) { RI.currententity = tr.draw_list->solid_entities[i]; RI.currentmodel = RI.currententity->model; - d_aflatcolor += 500; + //d_aflatcolor += 500; Assert( RI.currententity != NULL ); Assert( RI.currentmodel != NULL ); @@ -1908,9 +1904,6 @@ void R_NewMap (void) r_surfsonstack = true; } - r_maxedgesseen = 0; - r_maxsurfsseen = 0; - r_numallocatededges = sw_maxedges->value; if (r_numallocatededges < MINEDGES) diff --git a/r_misc.c b/r_misc.c index fbccc98b..27f7f857 100644 --- a/r_misc.c +++ b/r_misc.c @@ -33,11 +33,10 @@ float d_scalemip[NUM_MIPS-1]; static float basemip[NUM_MIPS-1] = {1.0, 0.5*0.8, 0.25*0.8}; -extern int d_aflatcolor; -int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle; +//int d_vrectx, d_vrecty, d_vrectright_particle, d_vrectbottom_particle; -int d_pix_min, d_pix_max, d_pix_shift; +//int d_pix_min, d_pix_max, d_pix_shift; int d_scantable[MAXHEIGHT]; short *zspantable[MAXHEIGHT]; @@ -73,7 +72,6 @@ void D_Patch (void) D_ViewChanged ================ */ -unsigned char *alias_colormap; void D_ViewChanged (void) { @@ -86,20 +84,20 @@ void D_ViewChanged (void) d_zrowbytes = vid.width * 2; d_zwidth = vid.width; - d_pix_min = gpGlobals->width / 320; + /*d_pix_min = gpGlobals->width / 320; if (d_pix_min < 1) d_pix_min = 1; d_pix_max = (int)((float)gpGlobals->height / (320.0 / 4.0) + 0.5); d_pix_shift = 8 - (int)((float)gpGlobals->height / 320.0 + 0.5); if (d_pix_max < 1) - d_pix_max = 1; + d_pix_max = 1;*/ - d_vrectx = RI.vrect.x; - d_vrecty = RI.vrect.y; - d_vrectright_particle = gpGlobals->width - d_pix_max; - d_vrectbottom_particle = - gpGlobals->height - d_pix_max; + //d_vrectx = RI.vrect.x; + //d_vrecty = RI.vrect.y; + //d_vrectright_particle = gpGlobals->width - d_pix_max; + //d_vrectbottom_particle = + // gpGlobals->height - d_pix_max; for (i=0 ; iwidth, gpGlobals->height,( int ) sw_clearcolor->value & 0xff ); } - alias_colormap = vid.colormap; - D_Patch (); } @@ -276,8 +272,8 @@ void R_ViewChanged (vrect_t *vr) yscale = xscale; aliasyscale = yscale * r_aliasuvscale; yscaleinv = 1.0 / yscale; - xscaleshrink = (RI.vrect.width-6)/RI.horizontalFieldOfView; - yscaleshrink = xscaleshrink; + //xscaleshrink = (RI.vrect.width-6)/RI.horizontalFieldOfView; + //yscaleshrink = xscaleshrink; // left side clip screenedge[0].normal[0] = -1.0 / (xOrigin*RI.horizontalFieldOfView); diff --git a/r_poly.c b/r_poly.c index fe03d18e..1a4264a1 100644 --- a/r_poly.c +++ b/r_poly.c @@ -39,7 +39,7 @@ typedef struct spanletvars_t s_spanletvars; -static int r_polyblendcolor; +//static int r_polyblendcolor; static espan_t *s_polygon_spans; @@ -1268,7 +1268,7 @@ void R_IMFlatShadedQuad( vec3_t a, vec3_t b, vec3_t c, vec3_t d, int color, floa r_polydesc.dist = DotProduct( r_polydesc.vpn, r_clip_verts[0][0] ); - r_polyblendcolor = color; + //r_polyblendcolor = color; R_ClipAndDrawPoly( alpha, false, false ); } diff --git a/r_polyse.c b/r_polyse.c index 6a2abe24..c9a75b1c 100644 --- a/r_polyse.c +++ b/r_polyse.c @@ -21,14 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // texture (used for Alias models) #include "r_local.h" -/* -int rand1k[] = { -#include "rand1k.h" -}; -*/ -#define MASK_1K 0x3FF - -int rand1k_index = 0; // TODO: put in span spilling to shrink list size // !!! if this is changed, it must be changed in d_polysa.s too !!! @@ -60,9 +52,6 @@ aliastriangleparms_t aliastriangleparms; int r_p0[6], r_p1[6], r_p2[6]; -byte *d_pcolormap; - -int d_aflatcolor; int d_xdenom; edgetable *pedgetable; @@ -120,7 +109,6 @@ void R_PolysetDrawSpans8_33 (spanpackage_t *pspanpackage); void R_PolysetDrawSpans8_66 (spanpackage_t *pspanpackage); void R_PolysetDrawSpans8_Opaque (spanpackage_t *pspanpackage); -void R_PolysetDrawThreshSpans8 (spanpackage_t *pspanpackage); void R_PolysetCalcGradients (int skinwidth); void R_DrawNonSubdiv (void); void R_PolysetSetEdgeTable (void); @@ -128,52 +116,6 @@ void R_RasterizeAliasPolySmooth (void); void R_PolysetScanLeftEdge(int height); void R_PolysetScanLeftEdge_C(int height); -// ====================== -// PGM -// 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 -byte iractive = 0; -byte irtable[256] = { 79, 78, 77, 76, 75, 74, 73, 72, // black/white - 71, 70, 69, 68, 67, 66, 65, 64, - 64, 65, 66, 67, 68, 69, 70, 71, // dark taupe - 72, 73, 74, 75, 76, 77, 78, 79, - - 64, 65, 66, 67, 68, 69, 70, 71, // slate grey - 72, 73, 74, 75, 76, 77, 78, 79, - 208, 208, 208, 208, 208, 208, 208, 208, // unused?' - 64, 66, 68, 70, 72, 74, 76, 78, // dark yellow - - 64, 65, 66, 67, 68, 69, 70, 71, // dark red - 72, 73, 74, 75, 76, 77, 78, 79, - 64, 65, 66, 67, 68, 69, 70, 71, // grey/tan - 72, 73, 74, 75, 76, 77, 78, 79, - - 64, 66, 68, 70, 72, 74, 76, 78, // chocolate - 68, 67, 66, 65, 64, 65, 66, 67, // mauve / teal - 68, 69, 70, 71, 72, 73, 74, 75, - 76, 76, 77, 77, 78, 78, 79, 79, - - 64, 65, 66, 67, 68, 69, 70, 71, // more mauve - 72, 73, 74, 75, 76, 77, 78, 79, - 64, 65, 66, 67, 68, 69, 70, 71, // olive - 72, 73, 74, 75, 76, 77, 78, 79, - - 64, 65, 66, 67, 68, 69, 70, 71, // maroon - 72, 73, 74, 75, 76, 77, 78, 79, - 64, 65, 66, 67, 68, 69, 70, 71, // sky blue - 72, 73, 74, 75, 76, 77, 78, 79, - - 64, 65, 66, 67, 68, 69, 70, 71, // olive again - 72, 73, 74, 75, 76, 77, 78, 79, - 64, 65, 66, 67, 68, 69, 70, 71, // nuclear green - 64, 65, 66, 67, 68, 69, 70, 71, // bright yellow - - 64, 65, 66, 67, 68, 69, 70, 71, // fire colors - 72, 73, 74, 75, 76, 77, 78, 79, - 208, 208, 64, 64, 70, 71, 72, 64, // mishmash1 - 66, 68, 70, 64, 65, 66, 67, 68}; // mishmash2 -// PGM -// ====================== - /* ================ R_PolysetUpdateTables @@ -739,82 +681,6 @@ void R_PolysetCalcGradients (int skinwidth) } #endif -/* -================ -R_PolysetDrawThreshSpans8 - -Random fizzle fade rasterizer -================ -*/ -void R_PolysetDrawThreshSpans8 (spanpackage_t *pspanpackage) -{ - int lcount; - byte *lpdest; - byte *lptex; - int lsfrac, ltfrac; - int llight; - int lzi; - short *lpz; - - do - { - lcount = d_aspancount - pspanpackage->count; - - errorterm += erroradjustup; - if (errorterm >= 0) - { - d_aspancount += d_countextrastep; - errorterm -= erroradjustdown; - } - else - { - d_aspancount += ubasestep; - } - - if (lcount) - { - lpdest = pspanpackage->pdest; - lptex = pspanpackage->ptex; - lpz = pspanpackage->pz; - lsfrac = pspanpackage->sfrac; - ltfrac = pspanpackage->tfrac; - llight = pspanpackage->light; - lzi = pspanpackage->zi; - - do - { - if ((lzi >> 16) >= *lpz) - { - rand1k_index = (rand1k_index + 1) & MASK_1K; - - /*if (rand1k[rand1k_index] <= r_affinetridesc.vis_thresh) - { - *lpdest = ((byte *)vid.colormap)[*lptex + (llight & 0xFF00)]; - *lpz = lzi >> 16; - }*/ - } - - lpdest++; - lzi += r_zistepx; - lpz++; - llight += r_lstepx; - lptex += a_ststepxwhole; - lsfrac += a_sstepxfrac; - lptex += lsfrac >> 16; - lsfrac &= 0xFFFF; - ltfrac += a_tstepxfrac; - if (ltfrac & 0x10000) - { - lptex += r_affinetridesc.skinwidth; - ltfrac &= 0xFFFF; - } - } while (--lcount); - } - - pspanpackage++; - } while (pspanpackage->count != -999999); -} - /* ================ diff --git a/r_scan.c b/r_scan.c index 4f078df2..0df3f8c9 100644 --- a/r_scan.c +++ b/r_scan.c @@ -26,7 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. pixel_t *r_turb_pbase, *r_turb_pdest; fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep; int *r_turb_turb; -int r_turb_spancount; +static int r_turb_spancount; void D_DrawTurbulent8Span (void); diff --git a/r_surf.c b/r_surf.c index 9081b83a..1e306c65 100644 --- a/r_surf.c +++ b/r_surf.c @@ -1204,7 +1204,7 @@ surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) // r_drawsurf.surf = surface; - c_surf++; + //c_surf++; // calculate the lightings R_BuildLightMap ( ); diff --git a/r_trialias.c b/r_trialias.c index 6c92eeac..88989cb4 100644 --- a/r_trialias.c +++ b/r_trialias.c @@ -2,17 +2,11 @@ // not really draw alias models here, but use this to draw triangles -int r_amodels_drawn; affinetridesc_t r_affinetridesc; -vec3_t r_plightvec; -vec3_t r_lerped[1024]; -vec3_t r_lerp_frontv, r_lerp_backv, r_lerp_move; -int r_ambientlight; int r_aliasblendcolor; -float r_shadelight; float aliastransform[3][4]; @@ -42,16 +36,6 @@ void R_AliasTransformFinalVerts( int numpoints, finalvert_t *fv, dtrivertx_t *ol R_AliasCheckBBox ================ */ -typedef struct { - int index0; - int index1; -} aedge_t; - -static aedge_t aedges[12] = { -{0, 1}, {1, 2}, {2, 3}, {3, 0}, -{4, 5}, {5, 6}, {6, 7}, {7, 4}, -{0, 5}, {1, 4}, {2, 7}, {3, 6} -}; #define BBOX_TRIVIAL_ACCEPT 0 #define BBOX_MUST_CLIP_XY 1 From 6879c1f097fc84e29301882c903bae439355be3b Mon Sep 17 00:00:00 2001 From: mittorn Date: Sun, 31 Mar 2019 03:18:03 +0700 Subject: [PATCH 049/115] ref_soft: Remove R_ConcatTransform, try fix transparent bmodels origin --- r_bsp.c | 33 +++++++++++++++++++++++++- r_local.h | 7 ------ r_main.c | 65 +++------------------------------------------------- r_poly.c | 5 ++-- r_trialias.c | 6 +++-- 5 files changed, 42 insertions(+), 74 deletions(-) diff --git a/r_bsp.c b/r_bsp.c index cdb8d6db..683e766a 100644 --- a/r_bsp.c +++ b/r_bsp.c @@ -48,6 +48,35 @@ static mvertex_t *pfrontenter, *pfrontexit; static qboolean makeclippededge; + +/* +================ +R_ConcatRotations +================ +*/ +void R_ConcatRotations (float in1[3][3], float in2[3][3], float out[3][3]) +{ + out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + + in1[0][2] * in2[2][0]; + out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + + in1[0][2] * in2[2][1]; + out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + + in1[0][2] * in2[2][2]; + out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + + in1[1][2] * in2[2][0]; + out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + + in1[1][2] * in2[2][1]; + out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + + in1[1][2] * in2[2][2]; + out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + + in1[2][2] * in2[2][0]; + out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + + in1[2][2] * in2[2][1]; + out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + + in1[2][2] * in2[2][2]; +} + + //=========================================================================== /* @@ -952,7 +981,7 @@ void R_DrawBrushModel(cl_entity_t *pent) if (pmodel->nummodelsurfaces == 0) return; // clip brush only -#if 0 +#if 1 // FIXME: use bounding-box-based frustum clipping info? RotatedBBox (pmodel->mins, pmodel->maxs, RI.currententity->angles, mins, maxs); @@ -969,6 +998,7 @@ void R_DrawBrushModel(cl_entity_t *pent) VectorCopy (RI.currententity->origin, r_entorigin); VectorSubtract (r_origin, r_entorigin, modelorg); //VectorSubtract (r_origin, RI.currententity->origin, modelorg); + r_pcurrentvertbase = pmodel->vertexes; // calculate dynamic lighting for bmodel @@ -989,6 +1019,7 @@ void R_DrawBrushModel(cl_entity_t *pent) #endif psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; numsurfaces = pmodel->nummodelsurfaces; + //R_TransformFrustum (); for (i=0 ; iflags, FCVAR_CHANGED ); + ClearBits( vid_gamma->flags, FCVAR_CHANGED ); } R_Set2DMode( true ); diff --git a/r_poly.c b/r_poly.c index 1a4264a1..0c7a1f9b 100644 --- a/r_poly.c +++ b/r_poly.c @@ -1057,13 +1057,14 @@ void R_BuildPolygonFromSurface(msurface_t *fa) vec = RI.currentmodel->vertexes[r_pedge->v[1]].position; } - VectorCopy (vec, pverts[i] ); + VectorAdd (vec, r_entorigin, pverts[i] ); + //VectorCopy( vec, pverts[i] ); } VectorCopy( fa->texinfo->vecs[0], r_polydesc.vright ); VectorCopy( fa->texinfo->vecs[1], r_polydesc.vup ); VectorCopy( fa->plane->normal, r_polydesc.vpn ); - VectorCopy( r_origin, r_polydesc.viewer_position ); + VectorCopy( modelorg, r_polydesc.viewer_position ); if ( fa->flags & SURF_PLANEBACK ) diff --git a/r_trialias.c b/r_trialias.c index 88989cb4..ab74ffae 100644 --- a/r_trialias.c +++ b/r_trialias.c @@ -122,7 +122,8 @@ void R_SetUpWorldTransform (void) // memcpy( aliasworldtransform, rotationmatrix, sizeof( aliastransform ) ); - R_ConcatTransforms (viewmatrix, aliasworldtransform, aliastransform); + //R_ConcatTransforms (viewmatrix, aliasworldtransform, aliastransform); + Matrix3x4_ConcatTransforms(aliastransform, viewmatrix, aliasworldtransform ); aliasworldtransform[0][3] = 0; aliasworldtransform[1][3] = 0; @@ -194,7 +195,8 @@ void R_AliasSetUpTransform (void) // memcpy( aliasworldtransform, rotationmatrix, sizeof( aliastransform ) ); - R_ConcatTransforms (viewmatrix, aliasworldtransform, aliastransform); + //R_ConcatTransforms (viewmatrix, aliasworldtransform, aliastransform); + Matrix3x4_ConcatTransforms(aliastransform, viewmatrix, aliasworldtransform ); aliasworldtransform[0][3] = RI.currententity->origin[0]; aliasworldtransform[1][3] = RI.currententity->origin[1]; From d315a838bd144d7782eb6faa415a83a09be8b1dc Mon Sep 17 00:00:00 2001 From: mittorn Date: Sun, 31 Mar 2019 03:44:57 +0700 Subject: [PATCH 050/115] ref_soft: invalidata all caches on dlight rebuild --- r_surf.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/r_surf.c b/r_surf.c index 1e306c65..533d7acf 100644 --- a/r_surf.c +++ b/r_surf.c @@ -1161,6 +1161,16 @@ surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) && cache->lightadj[3] == r_drawsurf.lightadj[3] ) return cache; + if( surface->dlightframe == r_framecount ) + { + int i; + // invalidate dlight cache + for( i = 0; i < 4; i++) + { + if( CACHESPOT(surface)[i] ) + CACHESPOT(surface)[i]->image = NULL; + } + } // // determine shape of surface // From 7fc09da4823d079aa5737b1e3405c7b5654c2448 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sun, 31 Mar 2019 18:00:25 +0700 Subject: [PATCH 051/115] ref_soft: TriAPI texturing, rendermodes --- r_image.c | 47 +++++++- r_local.h | 2 + r_main.c | 4 +- r_part.c | 3 + r_polyse.c | 324 +++++++++++++++++++++++++++++++++++++++++++++++++++ r_sprite.c | 8 +- r_studio.c | 10 +- r_trialias.c | 7 ++ r_triapi.c | 39 +++++-- 9 files changed, 420 insertions(+), 24 deletions(-) diff --git a/r_image.c b/r_image.c index bf577aaf..bdef18ab 100644 --- a/r_image.c +++ b/r_image.c @@ -42,9 +42,47 @@ GL_Bind */ void GL_Bind( int tmu, unsigned int texnum ) { - image_t *texture; + image_t *image; + + extern void (*d_pdrawspans)(void *); + extern void R_PolysetFillSpans8 ( void * ); + extern void R_PolysetDrawSpansConstant8_33( void *pspanpackage); + extern void R_PolysetDrawSpansTextureBlended( void *pspanpackage); + extern void R_PolysetDrawSpansBlended( void *pspanpackage); + extern void R_PolysetDrawSpansAdditive( void *pspanpackage); + extern void R_PolysetDrawSpansGlow( void *pspanpackage); - texture = &r_images[texnum]; + image = &r_images[texnum]; + //vid.rendermode = kRenderNormal; + + if( vid.rendermode == kRenderNormal ) + { + r_affinetridesc.pskin = image->pixels[0]; + d_pdrawspans = R_PolysetFillSpans8 ; + } + else if( vid.rendermode == kRenderTransAdd) + { + r_affinetridesc.pskin = image->pixels[0]; + d_pdrawspans = R_PolysetDrawSpansAdditive; + } + else if( vid.rendermode == kRenderGlow ) + { + r_affinetridesc.pskin = image->pixels[0]; + d_pdrawspans = R_PolysetDrawSpansGlow; + } + else if( image->alpha_pixels ) + { + r_affinetridesc.pskin = image->alpha_pixels; + d_pdrawspans = R_PolysetDrawSpansTextureBlended; + } + else + { + r_affinetridesc.pskin = image->pixels[0]; + d_pdrawspans = R_PolysetDrawSpansBlended; + } + + r_affinetridesc.skinwidth = image->width; + r_affinetridesc.skinheight = image->height; } /* @@ -533,7 +571,10 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) //GL_TextureImageRAW( tex, i, j, width, height, tex->depth, pic->type, data ); // increase size to workaround triangle renderer bugs // it seems to assume memory readable. maybe it was pointed to WAD? - tex->pixels[j] = (byte*)Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 1024 ) + 512; + tex->pixels[j] = (byte*)Mem_Malloc( r_temppool, width * height * sizeof(pixel_t) + 1024 ) + 512; + memset( (byte*)tex->pixels[j] - 512, 0xFF, 512 ); + memset( (byte*)tex->pixels[j] + width * height * sizeof(pixel_t), 0xFF, 512 ); + if( j == 0 && tex->flags & TF_HAS_ALPHA ) tex->alpha_pixels = (byte*)Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 256 ) + 128; diff --git a/r_local.h b/r_local.h index a644ad61..9a500ae1 100644 --- a/r_local.h +++ b/r_local.h @@ -1340,6 +1340,8 @@ void R_SetUpWorldTransform (void); #define BLEND_ALPHA_LOW(alpha, src, screen) (vid.alphamap[(alpha << 18) |( (src & 0xff00) << 2) | (screen >> 6)] | screen & 0x3f) #define BLEND_ALPHA(alpha, src, dst) alpha > 3?BLEND_ALPHA_LOW(7 - 1 - alpha, dst,src):BLEND_ALPHA_LOW(alpha-1, src, dst) +#define BLEND_ADD(src, screen) vid.addmap[ src& 0xff00|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 0); +#define BLEND_COLOR(src, color) vid.modmap[src & 0xff00|(color>>8)] << 8 | (src & color & 0xff) | ((src & 0xff) >> 3); // // engine callbacks diff --git a/r_main.c b/r_main.c index 46894155..5d759685 100644 --- a/r_main.c +++ b/r_main.c @@ -976,6 +976,7 @@ void R_DrawEntitiesOnList( void ) extern void R_PolysetDrawSpansConstant8_33( void *pspanpackage); extern void R_PolysetDrawSpans8_33( void *pspanpackage); d_pdrawspans = R_PolysetFillSpans8; + GL_SetRenderMode(kRenderNormal); // first draw solid entities for( i = 0; i < tr.draw_list->num_solid_entities && !RI.onlyClientDraw; i++ ) { @@ -1120,8 +1121,7 @@ void R_DrawEntitiesOnList( void ) //GL_CheckForErrors(); // pglDisable( GL_BLEND ); // Trinity Render issues - d_pdrawspans = R_PolysetFillSpans8; - + GL_SetRenderMode(kRenderNormal); R_SetUpWorldTransform(); if( !RI.onlyClientDraw ) R_DrawViewModel(); diff --git a/r_part.c b/r_part.c index 02c10ab3..151b3234 100644 --- a/r_part.c +++ b/r_part.c @@ -60,6 +60,7 @@ void CL_DrawParticles( double frametime, particle_t *cl_active_particles, float //pglEnable( GL_BLEND ); //pglDisable( GL_ALPHA_TEST ); //pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + GL_SetRenderMode( kRenderTransAdd ); GL_Bind( XASH_TEXTURE0, tr.particleTexture ); //pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); @@ -182,6 +183,8 @@ void CL_DrawTracers( double frametime, particle_t *cl_active_tracers ) if( !cl_active_tracers ) return; // nothing to draw? + GL_SetRenderMode( kRenderTransAdd ); + if( !TriSpriteTexture( gEngfuncs.GetDefaultSprite( REF_DOT_SPRITE ), 0 )) return; diff --git a/r_polyse.c b/r_polyse.c index c9a75b1c..b1719a33 100644 --- a/r_polyse.c +++ b/r_polyse.c @@ -682,6 +682,330 @@ void R_PolysetCalcGradients (int skinwidth) #endif +/* +================ +R_PolysetDrawSpans8 +================ +*/ +void R_PolysetDrawSpansBlended( spanpackage_t *pspanpackage) +{ + int lcount; + pixel_t *lpdest; + pixel_t *lptex; + int lsfrac, ltfrac; + int llight; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + { + d_aspancount += ubasestep; + } + + if (lcount) + { + lpdest = pspanpackage->pdest; + lptex = pspanpackage->ptex; + lpz = pspanpackage->pz; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + llight = pspanpackage->light; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) >= *lpz) + { +#if 0 + if((int)(lptex - (pixel_t*)r_affinetridesc.pskin) > r_affinetridesc.skinwidth * r_affinetridesc.skinheight || (int)(lptex - (pixel_t*)r_affinetridesc.pskin) < 0 ) + { + printf("%d %d %d %d\n",(int)(lptex - (pixel_t*)r_affinetridesc.pskin), r_affinetridesc.skinwidth * r_affinetridesc.skinheight, lsfrac, a_ststepxwhole ); + return; + } +#endif + pixel_t temp = *lptex;//vid.colormap[*lptex + ( llight & 0xFF00 )]; + temp = BLEND_COLOR(temp, vid.color); + + int alpha = vid.alpha; + if( alpha == 7 ) + *lpdest = temp; + else if(alpha) + *lpdest = BLEND_ALPHA(alpha,temp,*lpdest);//vid.alphamap[temp+ *lpdest*256]; + } + lpdest++; + lzi += r_zistepx; + lpz++; + llight += r_lstepx; + lptex += a_ststepxwhole; + lsfrac += a_sstepxfrac; + lptex += lsfrac >> 16; + lsfrac &= 0xFFFF; + ltfrac += a_tstepxfrac; + if (ltfrac & 0x10000) + { + lptex += r_affinetridesc.skinwidth; + ltfrac &= 0xFFFF; + } + } while (--lcount); + } + + pspanpackage++; + } while (pspanpackage->count != -999999); +} + + +/* +================ +R_PolysetDrawSpans8 +================ +*/ +void R_PolysetDrawSpansAdditive( spanpackage_t *pspanpackage) +{ + int lcount; + pixel_t *lpdest; + pixel_t *lptex; + int lsfrac, ltfrac; + int llight; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + { + d_aspancount += ubasestep; + } + + if (lcount) + { + lpdest = pspanpackage->pdest; + lptex = pspanpackage->ptex; + lpz = pspanpackage->pz; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + llight = pspanpackage->light; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) >= *lpz) + { +#if 0 + if((int)(lptex - (pixel_t*)r_affinetridesc.pskin) > r_affinetridesc.skinwidth * r_affinetridesc.skinheight || (int)(lptex - (pixel_t*)r_affinetridesc.pskin) < 0 ) + { + printf("%d %d %d %d\n",(int)(lptex - (pixel_t*)r_affinetridesc.pskin), r_affinetridesc.skinwidth * r_affinetridesc.skinheight, lsfrac, a_ststepxwhole ); + return; + } +#endif + pixel_t temp = *lptex;//vid.colormap[*lptex + ( llight & 0xFF00 )]; + temp = BLEND_COLOR(temp, vid.color); + + *lpdest = BLEND_ADD(temp,*lpdest); + + } + lpdest++; + lzi += r_zistepx; + lpz++; + llight += r_lstepx; + lptex += a_ststepxwhole; + lsfrac += a_sstepxfrac; + lptex += lsfrac >> 16; + lsfrac &= 0xFFFF; + ltfrac += a_tstepxfrac; + if (ltfrac & 0x10000) + { + lptex += r_affinetridesc.skinwidth; + ltfrac &= 0xFFFF; + } + } while (--lcount); + } + + pspanpackage++; + } while (pspanpackage->count != -999999); +} + + +/* +================ +R_PolysetDrawSpans8 +================ +*/ +void R_PolysetDrawSpansGlow( spanpackage_t *pspanpackage) +{ + int lcount; + pixel_t *lpdest; + pixel_t *lptex; + int lsfrac, ltfrac; + int llight; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + { + d_aspancount += ubasestep; + } + + if (lcount) + { + lpdest = pspanpackage->pdest; + lptex = pspanpackage->ptex; + lpz = pspanpackage->pz; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + llight = pspanpackage->light; + lzi = pspanpackage->zi; + + do + { + //if ((lzi >> 16) >= *lpz) + { +#if 0 + if((int)(lptex - (pixel_t*)r_affinetridesc.pskin) > r_affinetridesc.skinwidth * r_affinetridesc.skinheight || (int)(lptex - (pixel_t*)r_affinetridesc.pskin) < 0 ) + { + printf("%d %d %d %d\n",(int)(lptex - (pixel_t*)r_affinetridesc.pskin), r_affinetridesc.skinwidth * r_affinetridesc.skinheight, lsfrac, a_ststepxwhole ); + return; + } +#endif + pixel_t temp = *lptex;//vid.colormap[*lptex + ( llight & 0xFF00 )]; + temp = BLEND_COLOR(temp, vid.color); + + *lpdest = BLEND_ADD(temp,*lpdest); + + } + lpdest++; + lzi += r_zistepx; + lpz++; + llight += r_lstepx; + lptex += a_ststepxwhole; + lsfrac += a_sstepxfrac; + lptex += lsfrac >> 16; + lsfrac &= 0xFFFF; + ltfrac += a_tstepxfrac; + if (ltfrac & 0x10000) + { + lptex += r_affinetridesc.skinwidth; + ltfrac &= 0xFFFF; + } + } while (--lcount); + } + + pspanpackage++; + } while (pspanpackage->count != -999999); +} + + +/* +================ +R_PolysetDrawSpans8 +================ +*/ +void R_PolysetDrawSpansTextureBlended( spanpackage_t *pspanpackage) +{ + int lcount; + pixel_t *lpdest; + pixel_t *lptex; + int lsfrac, ltfrac; + int llight; + int lzi; + short *lpz; + + do + { + lcount = d_aspancount - pspanpackage->count; + + errorterm += erroradjustup; + if (errorterm >= 0) + { + d_aspancount += d_countextrastep; + errorterm -= erroradjustdown; + } + else + { + d_aspancount += ubasestep; + } + + if (lcount) + { + lpdest = pspanpackage->pdest; + lptex = pspanpackage->ptex; + lpz = pspanpackage->pz; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + llight = pspanpackage->light; + lzi = pspanpackage->zi; + + do + { + if ((lzi >> 16) >= *lpz) + { +#if 0 + if((int)(lptex - (pixel_t*)r_affinetridesc.pskin) > r_affinetridesc.skinwidth * r_affinetridesc.skinheight || (int)(lptex - (pixel_t*)r_affinetridesc.pskin) < 0 ) + { + printf("%d %d %d %d\n",(int)(lptex - (pixel_t*)r_affinetridesc.pskin), r_affinetridesc.skinwidth * r_affinetridesc.skinheight, lsfrac, a_ststepxwhole ); + return; + } +#endif + pixel_t temp = *lptex;//vid.colormap[*lptex + ( llight & 0xFF00 )]; + + int alpha = temp >> 13; + temp = temp << 3; + temp = BLEND_COLOR(temp, vid.color); + if( alpha == 7 ) + *lpdest = temp; + else if(alpha) + *lpdest = BLEND_ALPHA(alpha,temp,*lpdest);//vid.alphamap[temp+ *lpdest*256]; + } + lpdest++; + lzi += r_zistepx; + lpz++; + llight += r_lstepx; + lptex += a_ststepxwhole; + lsfrac += a_sstepxfrac; + lptex += lsfrac >> 16; + lsfrac &= 0xFFFF; + ltfrac += a_tstepxfrac; + if (ltfrac & 0x10000) + { + lptex += r_affinetridesc.skinwidth; + ltfrac &= 0xFFFF; + } + } while (--lcount); + } + + pspanpackage++; + } while (pspanpackage->count != -999999); +} + + + /* ================ R_PolysetDrawSpans8 diff --git a/r_sprite.c b/r_sprite.c index b6afac8e..91fd76e3 100644 --- a/r_sprite.c +++ b/r_sprite.c @@ -671,7 +671,9 @@ static float R_SpriteGlowBlend( vec3_t origin, int rendermode, int renderfx, flo tr = gEngfuncs.EV_VisTraceLine( RI.vieworg, origin, r_traceglow->value ? PM_GLASS_IGNORE : (PM_GLASS_IGNORE|PM_STUDIO_IGNORE)); if(( 1.0f - tr->fraction ) * dist > 8.0f ) + { return 0.0f; + } } if( renderfx == kRenderFxNoDissipation ) @@ -731,10 +733,10 @@ static void R_DrawSpriteQuad( mspriteframe_t *frame, vec3_t org, vec3_t v_right, image_t *image; r_stats.c_sprite_polys++; - image = R_GetTexture(frame->gl_texturenum); + /*image = R_GetTexture(frame->gl_texturenum); r_affinetridesc.pskin = image->pixels[0]; r_affinetridesc.skinwidth = image->width; - r_affinetridesc.skinheight = image->height; + r_affinetridesc.skinheight = image->height;*/ TriBegin( TRI_QUADS ); TriTexCoord2f( 0.0f, 1.0f ); @@ -920,6 +922,8 @@ void R_DrawSpriteModel( cl_entity_t *e ) if( e->curstate.rendermode == kRenderGlow || e->curstate.rendermode == kRenderTransAdd ) R_AllowFog( false ); + + GL_SetRenderMode( e->curstate.rendermode ); #if 0 // select properly rendermode switch( e->curstate.rendermode ) diff --git a/r_studio.c b/r_studio.c index 4b99f998..64b653ea 100644 --- a/r_studio.c +++ b/r_studio.c @@ -1814,14 +1814,10 @@ R_StudioSetupSkin static void R_StudioSetupSkin( studiohdr_t *ptexturehdr, int index ) { mstudiotexture_t *ptexture = NULL; - image_t *image; if( FBitSet( g_nForceFaceFlags, STUDIO_NF_CHROME )) { - image = R_GetTexture(tr.whiteTexture); - r_affinetridesc.pskin = image->pixels[0]; - r_affinetridesc.skinwidth = image->width; - r_affinetridesc.skinheight = image->height; + GL_Bind( XASH_TEXTURE0, tr.whiteTexture); return; } @@ -1835,10 +1831,6 @@ static void R_StudioSetupSkin( studiohdr_t *ptexturehdr, int index ) if( r_lightmap->value && !r_fullbright->value ) GL_Bind( XASH_TEXTURE0, tr.whiteTexture ); else GL_Bind( XASH_TEXTURE0, ptexture[index].index ); - image = R_GetTexture(ptexture[index].index); - r_affinetridesc.pskin = image->pixels[0]; - r_affinetridesc.skinwidth = image->width; - r_affinetridesc.skinheight = image->height; } /* diff --git a/r_trialias.c b/r_trialias.c index ab74ffae..4c74c533 100644 --- a/r_trialias.c +++ b/r_trialias.c @@ -238,6 +238,13 @@ void R_AliasProjectAndClipTestFinalVert( finalvert_t *fv ) fv->flags |= ALIAS_BOTTOM_CLIP; } +void R_AliasWorldToScreen( const float *v, float *out ) +{ + out[0] = DotProduct(v, aliastransform[0]) + aliastransform[0][3]; + out[1] = DotProduct(v, aliastransform[1]) + aliastransform[1][3]; + out[2] = DotProduct(v, aliastransform[2]) + aliastransform[2][3]; +} + void R_SetupFinalVert( finalvert_t *fv, float x, float y, float z, int light, int s, int t ) { vec3_t v = {x, y, z}; diff --git a/r_triapi.c b/r_triapi.c index 7491ec16..58aa67fe 100644 --- a/r_triapi.c +++ b/r_triapi.c @@ -155,7 +155,7 @@ void _TriColor4f( float rr, float gg, float bb, float aa ) if( light > 31 ) light = 31; - if( !vid.is2d ) + if( !vid.is2d && vid.rendermode == kRenderNormal ) return; vid.alpha = aa * 7; @@ -168,6 +168,12 @@ void _TriColor4f( float rr, float gg, float bb, float aa ) return; } r = rr * 31, g = gg * 63, b = bb * 31; + if( r > 31 ) + r = 31; + if( g > 63 ) + g = 63; + if( b > 31 ) + b = 31; major = (((r >> 2) & MASK(3)) << 5) |( (( (g >> 3) & MASK(3)) << 2 ) )| (((b >> 3) & MASK(2))); @@ -191,7 +197,7 @@ void TriColor4ub( byte r, byte g, byte b, byte a ) ds.triRGBA[2] = b * (1.0f / 255.0f); ds.triRGBA[3] = a * (1.0f / 255.0f); - _TriColor4f( ds.triRGBA[0], ds.triRGBA[1], ds.triRGBA[2], ds.triRGBA[3] ); //1.0f ); + _TriColor4f( ds.triRGBA[0], ds.triRGBA[1], ds.triRGBA[2], 1.0f ); } /* @@ -201,8 +207,10 @@ TriColor4f */ void TriColor4f( float r, float g, float b, float a ) { + //if( a < 0.5 ) + // a = 1; if( ds.renderMode == kRenderTransAlpha ) - TriColor4ub( r * 255.9f, g * 255.9f, b * 255.9f, a * 255.0f ); + TriColor4ub( r * 255.0f, g * 255.0f, b * 255.0f, a * 255.0f ); else _TriColor4f( r * a, g * a, b * a, 1.0 ); ds.triRGBA[0] = r; @@ -220,8 +228,17 @@ TriTexCoord2f void TriTexCoord2f( float u, float v ) { //pglTexCoord2f( u, v ); - s = r_affinetridesc.skinwidth * bound(0,u,1); - t = r_affinetridesc.skinheight * bound(0,v,1); + while( u < 0 ) + u = u + 1; + while( v < 0 ) + v = v + 1; + + while( u > 1 ) + u = u - 1; + while( v > 1 ) + v = v - 1; + s = r_affinetridesc.skinwidth * bound(0.01,u,0.99); + t = r_affinetridesc.skinheight * bound(0.01,v,0.99); } /* @@ -251,7 +268,7 @@ void TriVertex3f( float x, float y, float z ) if( vertcount == 3 ) { R_RenderTriangle( &triv[0], &triv[1], &triv[2] ); - R_RenderTriangle( &triv[2], &triv[1], &triv[0] ); + //R_RenderTriangle( &triv[2], &triv[1], &triv[0] ); vertcount = 0; } } @@ -262,6 +279,7 @@ void TriVertex3f( float x, float y, float z ) if( vertcount >= 3 ) { R_RenderTriangle( &triv[0], &triv[1], &triv[2] ); + //R_RenderTriangle( &triv[2], &triv[1], &triv[0] ); triv[1] = triv[2]; vertcount = 2; } @@ -305,7 +323,7 @@ void TriVertex3f( float x, float y, float z ) } #endif } - +void R_AliasWorldToScreen( const float *v, float *out ); /* ============= TriWorldToScreen @@ -317,7 +335,9 @@ int TriWorldToScreen( const float *world, float *screen ) { int retval; -// retval = R_WorldToScreen( world, screen ); + R_AliasWorldToScreen( world, screen ); + retval = 0; + screen[0] = 0.5f * screen[0] * (float)RI.viewport[2]; screen[1] = -0.5f * screen[1] * (float)RI.viewport[3]; @@ -451,6 +471,9 @@ void TriBrightness( float brightness ) { float r, g, b; + //if( brightness < 0.5 ) +// brightness = 1; //0.5; +//ds.triRGBA[3] = 1; r = ds.triRGBA[0] * ds.triRGBA[3] * brightness; g = ds.triRGBA[1] * ds.triRGBA[3] * brightness; b = ds.triRGBA[2] * ds.triRGBA[3] * brightness; From 2efdf56317860927938c7b1ad65fdf32cbf54edb Mon Sep 17 00:00:00 2001 From: mittorn Date: Sun, 31 Mar 2019 19:07:55 +0700 Subject: [PATCH 052/115] ref_soft: fix particles --- r_image.c | 6 +++--- r_main.c | 15 +++++++-------- r_part.c | 17 +++++++++++------ 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/r_image.c b/r_image.c index bdef18ab..2d34959d 100644 --- a/r_image.c +++ b/r_image.c @@ -571,9 +571,9 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) //GL_TextureImageRAW( tex, i, j, width, height, tex->depth, pic->type, data ); // increase size to workaround triangle renderer bugs // it seems to assume memory readable. maybe it was pointed to WAD? - tex->pixels[j] = (byte*)Mem_Malloc( r_temppool, width * height * sizeof(pixel_t) + 1024 ) + 512; - memset( (byte*)tex->pixels[j] - 512, 0xFF, 512 ); - memset( (byte*)tex->pixels[j] + width * height * sizeof(pixel_t), 0xFF, 512 ); + tex->pixels[j] = (byte*)Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 1024 ) + 512; + //memset( (byte*)tex->pixels[j] - 512, 0xFF, 512 ); + //memset( (byte*)tex->pixels[j] + width * height * sizeof(pixel_t), 0xFF, 512 ); if( j == 0 && tex->flags & TF_HAS_ALPHA ) tex->alpha_pixels = (byte*)Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 256 ) + 128; diff --git a/r_main.c b/r_main.c index 5d759685..6e21ee2c 100644 --- a/r_main.c +++ b/r_main.c @@ -478,20 +478,19 @@ R_SetupFrustum */ void R_SetupFrustum( void ) { - AngleVectors( RI.viewangles, RI.vforward, RI.vright, RI.vup ); -#if 0 +#if 1 ref_overview_t *ov = gEngfuncs.GetOverviewParms(); - if( RP_NORMALPASS() && ( gEngfuncs.GetWaterLevel() >= 3 )) + /*if( RP_NORMALPASS() && ( ENGINE_GET_PARM( PARM_WATER_LEVEL ) >= 3 )) { RI.fov_x = atan( tan( DEG2RAD( RI.fov_x ) / 2 ) * ( 0.97 + sin( gpGlobals->time * 1.5 ) * 0.03 )) * 2 / (M_PI / 180.0); RI.fov_y = atan( tan( DEG2RAD( RI.fov_y ) / 2 ) * ( 1.03 - sin( gpGlobals->time * 1.5 ) * 0.03 )) * 2 / (M_PI / 180.0); - } + }*/ // build the transformation matrix for the given view angles AngleVectors( RI.viewangles, RI.vforward, RI.vright, RI.vup ); - if( !r_lockfrustum->value ) + //if( !r_lockfrustum->value ) { VectorCopy( RI.vieworg, RI.cullorigin ); VectorCopy( RI.vforward, RI.cull_vforward ); @@ -499,9 +498,9 @@ void R_SetupFrustum( void ) VectorCopy( RI.vup, RI.cull_vup ); } - if( RI.drawOrtho ) - GL_FrustumInitOrtho( &RI.frustum, ov->xLeft, ov->xRight, ov->yTop, ov->yBottom, ov->zNear, ov->zFar ); - else GL_FrustumInitProj( &RI.frustum, 0.0f, R_GetFarClip(), RI.fov_x, RI.fov_y ); // NOTE: we ignore nearplane here (mirrors only) +// if( RI.drawOrtho ) +// GL_FrustumInitOrtho( &RI.frustum, ov->xLeft, ov->xRight, ov->yTop, ov->yBottom, ov->zNear, ov->zFar ); +// else GL_FrustumInitProj( &RI.frustum, 0.0f, R_GetFarClip(), RI.fov_x, RI.fov_y ); // NOTE: we ignore nearplane here (mirrors only) #endif } diff --git a/r_part.c b/r_part.c index 151b3234..5a1a361d 100644 --- a/r_part.c +++ b/r_part.c @@ -66,8 +66,6 @@ void CL_DrawParticles( double frametime, particle_t *cl_active_particles, float //pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); //pglDepthMask( GL_FALSE ); - TriBegin( TRI_QUADS ); - for( p = cl_active_particles; p; p = p->next ) { if(( p->type != pt_blob ) || ( p->packedColor == 255 )) @@ -93,10 +91,13 @@ void CL_DrawParticles( double frametime, particle_t *cl_active_particles, float if( alpha > 255 || p->type == pt_static ) alpha = 255; - TriColor4ub( gEngfuncs.LightToTexGamma( pColor->r ), - gEngfuncs.LightToTexGamma( pColor->g ), - gEngfuncs.LightToTexGamma( pColor->b ), alpha ); + //TriColor4ub( gEngfuncs.LightToTexGamma( pColor->r ), + // gEngfuncs.LightToTexGamma( pColor->g ), + // gEngfuncs.LightToTexGamma( pColor->b ), alpha ); + //TriBrightness( alpha / 255.0f ); + _TriColor4f(1.0f*alpha/255/255*pColor->r,1.0f*alpha/255/255*pColor->g,1.0f*alpha/255/255* pColor->b,1.0f ); + TriBegin( TRI_QUADS ); TriTexCoord2f( 0.0f, 1.0f ); TriVertex3f( p->org[0] - right[0] + up[0], p->org[1] - right[1] + up[1], p->org[2] - right[2] + up[2] ); TriTexCoord2f( 0.0f, 0.0f ); @@ -105,6 +106,7 @@ void CL_DrawParticles( double frametime, particle_t *cl_active_particles, float TriVertex3f( p->org[0] + right[0] - up[0], p->org[1] + right[1] - up[1], p->org[2] + right[2] - up[2] ); TriTexCoord2f( 1.0f, 1.0f ); TriVertex3f( p->org[0] - right[0] - up[0], p->org[1] - right[1] - up[1], p->org[2] - right[2] - up[2] ); + TriEnd(); r_stats.c_particle_count++; } @@ -211,6 +213,7 @@ void CL_DrawTracers( double frametime, particle_t *cl_active_tracers ) vec3_t verts[4], tmp2; vec3_t tmp, normal; color24 *pColor; + short alpha = p->packedColor; // Transform point into screen space TriWorldToScreen( start, screen ); @@ -241,7 +244,9 @@ void CL_DrawTracers( double frametime, particle_t *cl_active_tracers ) } pColor = &gTracerColors[p->color]; - TriColor4ub( pColor->r, pColor->g, pColor->b, p->packedColor ); + //TriColor4ub( pColor->r, pColor->g, pColor->b, p->packedColor ); + _TriColor4f(1.0f*alpha/255/255*pColor->r,1.0f*alpha/255/255*pColor->g,1.0f*alpha/255/255* pColor->b,1.0f ); + TriBegin( TRI_QUADS ); TriTexCoord2f( 0.0f, 0.8f ); From 714084bf5b2ef15a5bf26ad079e419996824c91e Mon Sep 17 00:00:00 2001 From: mittorn Date: Sun, 31 Mar 2019 20:57:29 +0700 Subject: [PATCH 053/115] ref_soft: Fix hang on big texcoords --- r_triapi.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/r_triapi.c b/r_triapi.c index 58aa67fe..cb477f5c 100644 --- a/r_triapi.c +++ b/r_triapi.c @@ -228,6 +228,12 @@ TriTexCoord2f void TriTexCoord2f( float u, float v ) { //pglTexCoord2f( u, v ); + u = fmod(u, 10); + v = fmod(v, 10); + if( isnan(u) ) + u = 0; + if( isnan(v)) + v = 0; while( u < 0 ) u = u + 1; while( v < 0 ) @@ -237,6 +243,8 @@ void TriTexCoord2f( float u, float v ) u = u - 1; while( v > 1 ) v = v - 1; + + s = r_affinetridesc.skinwidth * bound(0.01,u,0.99); t = r_affinetridesc.skinheight * bound(0.01,v,0.99); } From 1c49d76fb7bbffdd2402eb21878e93b557763049 Mon Sep 17 00:00:00 2001 From: mittorn Date: Mon, 1 Apr 2019 01:55:37 +0700 Subject: [PATCH 054/115] ref_soft: Fix some integer overflows --- r_polyse.c | 11 +++++++++++ r_rast.c | 12 ++++++++++++ r_triapi.c | 42 +++++++++++++++++++++--------------------- 3 files changed, 44 insertions(+), 21 deletions(-) diff --git a/r_polyse.c b/r_polyse.c index b1719a33..3f9fddce 100644 --- a/r_polyse.c +++ b/r_polyse.c @@ -306,6 +306,17 @@ void FloorDivMod (float numer, float denom, int *quotient, r = (int)denom - r; } } + if( q > INT_MAX / 2 || q < INT_MIN / 2 ) + { + gEngfuncs.Con_Printf( S_ERROR"FloorDivMod: q overflow!\n" ); + q = 1; + } + + if( r > INT_MAX / 2 || r < INT_MIN / 2 ) + { + gEngfuncs.Con_Printf( S_ERROR "FloorDivMod: r overflow!\n"); + r = 1; + } *quotient = q; *rem = r; diff --git a/r_rast.c b/r_rast.c index fee7619c..fb326714 100644 --- a/r_rast.c +++ b/r_rast.c @@ -332,6 +332,12 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) v = ceilv0; v2 = r_ceilv1 - 1; + if( v < 0 || v > MAXHEIGHT ) + { + gEngfuncs.Con_Printf( S_ERROR "trailing edge overflow : %d\n", v ); + return; + } + edge->surfs[0] = surface_p - surfaces; edge->surfs[1] = 0; @@ -344,6 +350,12 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) v2 = ceilv0 - 1; v = r_ceilv1; + if( v < 0 || v > MAXHEIGHT ) + { + gEngfuncs.Con_Printf( S_ERROR "leading edge overflow : %d\n", v ); + return; + } + edge->surfs[0] = 0; edge->surfs[1] = surface_p - surfaces; diff --git a/r_triapi.c b/r_triapi.c index cb477f5c..6b26752a 100644 --- a/r_triapi.c +++ b/r_triapi.c @@ -225,28 +225,28 @@ TriTexCoord2f ============= */ -void TriTexCoord2f( float u, float v ) +void TriTexCoord2f( volatile float u, volatile float v ) { - //pglTexCoord2f( u, v ); - u = fmod(u, 10); - v = fmod(v, 10); - if( isnan(u) ) - u = 0; - if( isnan(v)) - v = 0; - while( u < 0 ) - u = u + 1; - while( v < 0 ) - v = v + 1; - - while( u > 1 ) - u = u - 1; - while( v > 1 ) - v = v - 1; - - - s = r_affinetridesc.skinwidth * bound(0.01,u,0.99); - t = r_affinetridesc.skinheight * bound(0.01,v,0.99); + volatile double u1 = 0, v1 = 0; + u = fmodf(u, 10); + v = fmodf(v, 10); + if( u < 1000 && u > -1000 ) + u1 = u; + if( v < 1000 && v > -1000 ) + v1 = v; + while( u1 < 0 ) + u1 = u1 + 1; + while( v1 < 0 ) + v1 = v1 + 1; + + while( u1 > 1 ) + u1 = u1 - 1; + while( v1 > 1 ) + v1 = v1 - 1; + + + s = r_affinetridesc.skinwidth * bound(0,u1,1); + t = r_affinetridesc.skinheight * bound(0,v1,1); } /* From 0c6c0003b132d4f455f3964faad0648434030535 Mon Sep 17 00:00:00 2001 From: mittorn Date: Mon, 1 Apr 2019 02:42:13 +0700 Subject: [PATCH 055/115] ref_soft: Bound texcoords again, disable drawing spans on FloorDivMod overflow --- r_polyse.c | 11 ++++++++++- r_triapi.c | 4 ++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/r_polyse.c b/r_polyse.c index 3f9fddce..abededfa 100644 --- a/r_polyse.c +++ b/r_polyse.c @@ -105,6 +105,11 @@ byte *skinstart; void (*d_pdrawspans)(spanpackage_t *pspanpackage); +void R_PolysetStub (spanpackage_t *pspanpackage) +{ + +} + void R_PolysetDrawSpans8_33 (spanpackage_t *pspanpackage); void R_PolysetDrawSpans8_66 (spanpackage_t *pspanpackage); void R_PolysetDrawSpans8_Opaque (spanpackage_t *pspanpackage); @@ -308,12 +313,16 @@ void FloorDivMod (float numer, float denom, int *quotient, } if( q > INT_MAX / 2 || q < INT_MIN / 2 ) { - gEngfuncs.Con_Printf( S_ERROR"FloorDivMod: q overflow!\n" ); + int i; + d_pdrawspans = R_PolysetStub; + gEngfuncs.Con_Printf( S_ERROR "FloorDivMod: q overflow!\n" ); q = 1; } if( r > INT_MAX / 2 || r < INT_MIN / 2 ) { + int i; + d_pdrawspans = R_PolysetStub; gEngfuncs.Con_Printf( S_ERROR "FloorDivMod: r overflow!\n"); r = 1; } diff --git a/r_triapi.c b/r_triapi.c index 6b26752a..8b61b38b 100644 --- a/r_triapi.c +++ b/r_triapi.c @@ -245,8 +245,8 @@ void TriTexCoord2f( volatile float u, volatile float v ) v1 = v1 - 1; - s = r_affinetridesc.skinwidth * bound(0,u1,1); - t = r_affinetridesc.skinheight * bound(0,v1,1); + s = r_affinetridesc.skinwidth * bound(0.01,u1,0.99); + t = r_affinetridesc.skinheight * bound(0.01,v1,0.99); } /* From 77f8da275a0d5829ca79a212f30bc2d54ebd3f16 Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 3 Apr 2019 22:20:33 +0700 Subject: [PATCH 056/115] ref_soft: Extend edge drawing with zbuffer support, draw transparent brushes with it --- r_bsp.c | 103 ---------- r_edge.c | 118 +++++++++++- r_main.c | 157 ++++++++++++++++ r_scan.c | 564 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 837 insertions(+), 105 deletions(-) diff --git a/r_bsp.c b/r_bsp.c index 683e766a..3fcbb62d 100644 --- a/r_bsp.c +++ b/r_bsp.c @@ -947,106 +947,3 @@ void R_RenderWorld (void) R_RecursiveWorldNode (RI.currentmodel->nodes, 15); } - - - -/* -================ -R_DrawBrushModel - -not covered by edge drawing -================ -*/ -void R_DrawBrushModel(cl_entity_t *pent) -{ - int i; - vec_t dot; - msurface_t *psurf; - int numsurfaces; - mplane_t *pplane; - vec3_t mins, maxs; - float minmaxs[6]; - int clipflags, k; - model_t *pmodel; - vec3_t oldorigin; - VectorCopy (modelorg, oldorigin); - insubmodel = true; - if( !pent || !pent->model ) - return; - - pmodel = pent->model; - - if (pmodel->type != mod_brush) - return; - - if (pmodel->nummodelsurfaces == 0) - return; // clip brush only -#if 1 -// FIXME: use bounding-box-based frustum clipping info? - RotatedBBox (pmodel->mins, pmodel->maxs, - RI.currententity->angles, mins, maxs); - - VectorAdd (mins, RI.currententity->origin, minmaxs); - VectorAdd (maxs, RI.currententity->origin, (minmaxs+3)); - - clipflags = R_BmodelCheckBBox (minmaxs); - if (clipflags == BMODEL_FULLY_CLIPPED) - return; // off the edge of the screen - - R_RotateBmodel (); - - VectorCopy (RI.currententity->origin, r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); - //VectorSubtract (r_origin, RI.currententity->origin, modelorg); - - r_pcurrentvertbase = pmodel->vertexes; - - // calculate dynamic lighting for bmodel - for( k = 0; k < MAX_DLIGHTS; k++ ) - { - dlight_t *l = gEngfuncs.GetDynamicLight( k ); - - if( l->die < gpGlobals->time || !l->radius ) - continue; - - /*VectorCopy( l->origin, oldorigin ); // save lightorigin - Matrix4x4_VectorITransform( RI.objectMatrix, l->origin, origin_l ); - VectorCopy( origin_l, l->origin ); // move light in bmodel space - R_MarkLights( l, 1<nodes + clmodel->hulls[0].firstclipnode ); - VectorCopy( oldorigin, l->origin ); // restore lightorigin*/ - R_MarkLights( l, 1<nodes + pmodel->hulls[0].firstclipnode ); - } -#endif - psurf = &pmodel->surfaces[pmodel->firstmodelsurface]; - numsurfaces = pmodel->nummodelsurfaces; - //R_TransformFrustum (); - - for (i=0 ; iplane; - - dot = DotProduct (modelorg, pplane->normal) - pplane->dist; - - // draw the polygon - if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || - (!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) - { - - // FIXME: use bounding-box-based frustum clipping info? - R_BuildPolygonFromSurface( psurf ); - R_ClipAndDrawPoly( pent->curstate.renderamt / 255, !!(psurf->flags & SURF_DRAWTURB), true ); - - } - } - - // put back world rotation and frustum clipping - // FIXME: R_RotateBmodel should just work off base_vxx - VectorCopy (base_vpn, vpn); - VectorCopy (base_vup, vup); - VectorCopy (base_vright, vright); - VectorCopy (oldorigin, modelorg); - R_TransformFrustum (); -} - - diff --git a/r_edge.c b/r_edge.c index 490204f6..e20d3908 100644 --- a/r_edge.c +++ b/r_edge.c @@ -981,6 +981,109 @@ void D_SkySurf (surf_t *s) D_DrawZSpans (s->spans); } +qboolean alphaspans; + + +void D_AlphaSpans16 (espan_t *pspan); +void D_BlendSpans16 (espan_t *pspan, int alpha ); +void TurbulentZ8 (espan_t *pspan, int alpha ); +/* +============== +D_SolidSurf + +Normal surface cached, texture mapped surface +============== +*/ +void D_AlphaSurf (surf_t *s) +{ + d_zistepu = s->d_zistepu; + d_zistepv = s->d_zistepv; + d_ziorigin = s->d_ziorigin; + if(s->flags & SURF_DRAWSKY) + return; + if (!s->insubmodel) // wtf? how it is possible? + return; + +// FIXME: we don't want to do all this for every polygon! +// TODO: store once at start of frame + RI.currententity = s->entity; //FIXME: make this passed in to + // R_RotateBmodel () + VectorSubtract (RI.vieworg, RI.currententity->origin, local_modelorg); + TransformVector (local_modelorg, transformed_modelorg); + + R_RotateBmodel (); // FIXME: don't mess with the frustum, + // make entity passed in + + + pface = s->msurf; + + + if( !pface ) + return; +#if 1 + + if( pface->flags & SURF_CONVEYOR ) + miplevel = 1; + else + miplevel = 0; +#else + { + float dot; + float normal[3]; + + if ( s->insubmodel ) + { + VectorCopy( pface->plane->normal, normal ); +// TransformVector( pface->plane->normal, normal); + dot = DotProduct( normal, vpn ); + } + else + { + VectorCopy( pface->plane->normal, normal ); + dot = DotProduct( normal, vpn ); + } + + if ( pface->flags & SURF_PLANEBACK ) + dot = -dot; + + if ( dot > 0 ) + printf( "blah" ); + + miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip * pface->texinfo->mipadjust); + } +#endif + + if (s->flags & SURF_DRAWTURB ) + { + cacheblock = R_GetTexture(pface->texinfo->texture->gl_texturenum)->pixels[0]; + cachewidth = 64; + D_CalcGradients (pface); + TurbulentZ8( s->spans, RI.currententity->curstate.renderamt * 7 / 255 ); + } + else + { + // FIXME: make this passed in to D_CacheSurface + pcurrentcache = D_CacheSurface (pface, miplevel); + + cacheblock = (pixel_t *)pcurrentcache->data; + cachewidth = pcurrentcache->width; + + D_CalcGradients (pface); + + if( RI.currententity->curstate.rendermode == kRenderTransAlpha ) + D_AlphaSpans16(s->spans); + else + D_BlendSpans16(s->spans, RI.currententity->curstate.renderamt * 7 / 255 ); + } + + VectorCopy (world_transformed_modelorg, + transformed_modelorg); + VectorCopy (base_vpn, vpn); + VectorCopy (base_vup, vup); + VectorCopy (base_vright, vright); + R_TransformFrustum (); +} + /* ============== @@ -994,6 +1097,10 @@ void D_SolidSurf (surf_t *s) d_zistepu = s->d_zistepu; d_zistepv = s->d_zistepv; d_ziorigin = s->d_ziorigin; + if(s->flags & SURF_DRAWSKY) + return; + if (s->flags & SURF_DRAWTURB ) + return; if (s->insubmodel) { @@ -1008,7 +1115,11 @@ void D_SolidSurf (surf_t *s) // make entity passed in } else + { + if( alphaspans ) + return; RI.currententity = gEngfuncs.GetEntityByIndex(0); //r_worldentity; + } pface = s->msurf; @@ -1017,6 +1128,7 @@ void D_SolidSurf (surf_t *s) return; #if 1 + if( pface->flags & SURF_CONVEYOR ) miplevel = 1; else @@ -1130,7 +1242,9 @@ void D_DrawSurfaces (void) //r_drawnpolycount++; #if 1 - if(s->flags & SURF_DRAWSKY) + if( alphaspans ) + D_AlphaSurf (s); + else if(s->flags & SURF_DRAWSKY) D_BackgroundSurf (s); else if (s->flags & SURF_DRAWTURB ) D_TurbulentSurf (s); @@ -1151,7 +1265,7 @@ void D_DrawSurfaces (void) else D_DrawflatSurfaces (); - RI.currententity = NULL; //&r_worldentity; + //RI.currententity = NULL; //&r_worldentity; VectorSubtract (RI.vieworg, vec3_origin, modelorg); R_TransformFrustum (); } diff --git a/r_main.c b/r_main.c index 6e21ee2c..3637b419 100644 --- a/r_main.c +++ b/r_main.c @@ -1403,6 +1403,163 @@ void R_DrawBEntitiesOnList (void) insubmodel = false; } + +extern qboolean alphaspans; +/* +============= +R_DrawBEntitiesOnList +============= +*/ +void R_DrawBrushModel(cl_entity_t *pent) +{ + int i, clipflags; + vec3_t oldorigin; + vec3_t mins, maxs; + float minmaxs[6]; + mnode_t *topnode; + int k; + edge_t ledges[NUMSTACKEDGES + + ((CACHE_SIZE - 1) / sizeof(edge_t)) + 1]; + surf_t lsurfs[NUMSTACKSURFACES + + ((CACHE_SIZE - 1) / sizeof(surf_t)) + 1]; + + if ( !RI.drawWorld ) + return; + + if (auxedges) + { + r_edges = auxedges; + } + else + { + r_edges = (edge_t *) + (((long)&ledges[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); + } + + if (r_surfsonstack) + { + surfaces = (surf_t *) + (((long)&lsurfs[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); + surf_max = &surfaces[r_cnumsurfs]; + // surface 0 doesn't really exist; it's just a dummy because index 0 + // is used to indicate no edge attached to surface + memset(&surfaces[0], 0, sizeof(surf_t)); + surfaces--; + R_SurfacePatch (); + } + + + R_BeginEdgeFrame(); + + VectorCopy (modelorg, oldorigin); + insubmodel = true; + //r_dlightframecount = r_framecount; + + if (!RI.currentmodel) + return; + if (RI.currentmodel->nummodelsurfaces == 0) + return; // clip brush only + //if ( currententity->flags & RF_BEAM ) + //continue; + if (RI.currentmodel->type != mod_brush) + return; + // see if the bounding box lets us trivially reject, also sets + // trivial accept status + RotatedBBox (RI.currentmodel->mins, RI.currentmodel->maxs, + RI.currententity->angles, mins, maxs); +#if 0 + mins[0] = mins[0] - 100; + mins[1] = mins[1] - 100; + mins[2] = mins[2] - 100; + maxs[0] = maxs[0] + 100; + maxs[1] = maxs[1] + 100; + maxs[2] = maxs[2] + 100; +#endif + VectorAdd (mins, RI.currententity->origin, minmaxs); + VectorAdd (maxs, RI.currententity->origin, (minmaxs+3)); + + clipflags = R_BmodelCheckBBox (minmaxs); + if (clipflags == BMODEL_FULLY_CLIPPED) + return; // off the edge of the screen + //clipflags = 0; + + topnode = R_FindTopnode (minmaxs, minmaxs+3); + if (!topnode) + return; // no part in a visible leaf + + alphaspans = true; + VectorCopy (RI.currententity->origin, r_entorigin); + VectorSubtract (r_origin, r_entorigin, modelorg); + //VectorSubtract (r_origin, RI.currententity->origin, modelorg); + r_pcurrentvertbase = RI.currentmodel->vertexes; + + // FIXME: stop transforming twice + R_RotateBmodel (); + + // calculate dynamic lighting for bmodel + // this will reset RI.currententity, do we need this? + //R_PushDlights (); + /*if (clmodel->firstmodelsurface != 0) + { + for (k=0 ; knodes + clmodel->firstnode); + } + }*/ + + // calculate dynamic lighting for bmodel + for( k = 0; k < MAX_DLIGHTS; k++ ) + { + dlight_t *l = gEngfuncs.GetDynamicLight( k ); + + if( l->die < gpGlobals->time || !l->radius ) + continue; + + /*VectorCopy( l->origin, oldorigin ); // save lightorigin + Matrix4x4_VectorITransform( RI.objectMatrix, l->origin, origin_l ); + VectorCopy( origin_l, l->origin ); // move light in bmodel space + R_MarkLights( l, 1<nodes + clmodel->hulls[0].firstclipnode ); + VectorCopy( oldorigin, l->origin ); // restore lightorigin*/ + R_MarkLights( l, 1<nodes + RI.currentmodel->hulls[0].firstclipnode ); + } + + // RI.currentmodel = tr.draw_list->solid_entities[i]->model; + // RI.currententity = tr.draw_list->solid_entities[i]; + RI.currententity->topnode = topnode; +//ASSERT( RI.currentmodel == tr.draw_list->solid_entities[i]->model ); + if (topnode->contents >= 0) + { + // not a leaf; has to be clipped to the world BSP + r_clipflags = clipflags; + R_DrawSolidClippedSubmodelPolygons (RI.currentmodel, topnode); + } + else + { + // falls entirely in one leaf, so we just put all the + // edges in the edge list and let 1/z sorting handle + // drawing order + //ASSERT( RI.currentmodel == tr.draw_list->solid_entities[i]->model ); + + + R_DrawSubmodelPolygons (RI.currentmodel, clipflags, topnode); + } + RI.currententity->topnode = NULL; + + // put back world rotation and frustum clipping + // FIXME: R_RotateBmodel should just work off base_vxx + VectorCopy (base_vpn, vpn); + VectorCopy (base_vup, vup); + VectorCopy (base_vright, vright); + VectorCopy (oldorigin, modelorg); + R_TransformFrustum (); + + + insubmodel = false; + R_ScanEdges(); + alphaspans = false; +} + #endif /* diff --git a/r_scan.c b/r_scan.c index 0df3f8c9..8a31b90e 100644 --- a/r_scan.c +++ b/r_scan.c @@ -24,9 +24,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "r_local.h" pixel_t *r_turb_pbase, *r_turb_pdest; +short *r_turb_pz; fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep; +int r_turb_izistep, r_turb_izi; int *r_turb_turb; static int r_turb_spancount; +int alpha; void D_DrawTurbulent8Span (void); @@ -115,6 +118,36 @@ void D_DrawTurbulent8Span (void) } while (--r_turb_spancount > 0); } + +/* +============= +D_DrawTurbulent8Span +============= +*/ +void D_DrawTurbulent8ZSpan (void) +{ + int sturb, tturb; + + do + { + sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63; + tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63; + if (*r_turb_pz <= (r_turb_izi >> 16)) + { + pixel_t btemp = *(r_turb_pbase + (tturb<<6) + sturb); + if( alpha == 7 ) + *r_turb_pdest = btemp; + else + *r_turb_pdest = BLEND_ALPHA( alpha, btemp, *r_turb_pdest); + } + r_turb_pdest++; + r_turb_pz++; + r_turb_izi += r_turb_izistep; + r_turb_s += r_turb_sstep; + r_turb_t += r_turb_tstep; + } while (--r_turb_spancount > 0); +} + #endif // !id386 @@ -250,6 +283,146 @@ void Turbulent8 (espan_t *pspan) } while ((pspan = pspan->pnext) != NULL); } + +/* +============= +Turbulent8 +============= +*/ +void TurbulentZ8 (espan_t *pspan, int alpha1) +{ + int count; + fixed16_t snext, tnext; + float sdivz, tdivz, zi, z, du, dv, spancountminus1; + float sdivz16stepu, tdivz16stepu, zi16stepu; + alpha = alpha1; + + r_turb_turb = sintable + ((int)(gpGlobals->time*SPEED)&(CYCLE-1)); + + r_turb_sstep = 0; // keep compiler happy + r_turb_tstep = 0; // ditto + + r_turb_pbase = (unsigned char *)cacheblock; + + sdivz16stepu = d_sdivzstepu * 16; + tdivz16stepu = d_tdivzstepu * 16; + zi16stepu = d_zistepu * 16; + r_turb_izistep = (int)(d_zistepu * 0x8000 * 0x10000); + + do + { + r_turb_pdest = (d_viewbuffer + + (r_screenwidth * pspan->v) + pspan->u); + r_turb_pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; + + count = pspan->count; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float)pspan->u; + dv = (float)pspan->v; + + sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; + tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; + zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + r_turb_izi = (int)(zi * 0x8000 * 0x10000); + + r_turb_s = (int)(sdivz * z) + sadjust; + if (r_turb_s > bbextents) + r_turb_s = bbextents; + else if (r_turb_s < 0) + r_turb_s = 0; + + r_turb_t = (int)(tdivz * z) + tadjust; + if (r_turb_t > bbextentt) + r_turb_t = bbextentt; + else if (r_turb_t < 0) + r_turb_t = 0; + + do + { + // calculate s and t at the far end of the span + if (count >= 16) + r_turb_spancount = 16; + else + r_turb_spancount = count; + + count -= r_turb_spancount; + + if (count) + { + // calculate s/z, t/z, zi->fixed s and t at far end of span, + // calculate s and t steps across span by shifting + sdivz += sdivz16stepu; + tdivz += tdivz16stepu; + zi += zi16stepu; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 16) + snext = 16; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 16) + tnext = 16; // guard against round-off error on <0 steps + + r_turb_sstep = (snext - r_turb_s) >> 4; + r_turb_tstep = (tnext - r_turb_t) >> 4; + } + else + { + // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so + // can't step off polygon), clamp, calculate s and t steps across + // span by division, biasing steps low so we don't run off the + // texture + spancountminus1 = (float)(r_turb_spancount - 1); + sdivz += d_sdivzstepu * spancountminus1; + tdivz += d_tdivzstepu * spancountminus1; + zi += d_zistepu * spancountminus1; + + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 16) + snext = 16; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 16) + tnext = 16; // guard against round-off error on <0 steps + + if (r_turb_spancount > 1) + { + r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1); + r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1); + } + } + + r_turb_s = r_turb_s & ((CYCLE<<16)-1); + r_turb_t = r_turb_t & ((CYCLE<<16)-1); + + D_DrawTurbulent8ZSpan (); + + r_turb_s = snext; + r_turb_t = tnext; + + } while (count > 0); + + } while ((pspan = pspan->pnext) != NULL); +} + + + //==================== //PGM /* @@ -570,6 +743,397 @@ void D_DrawSpans16 (espan_t *pspan) } while ((pspan = pspan->pnext) != NULL); } + +/* +============= +D_DrawSpans16 + + FIXME: actually make this subdivide by 16 instead of 8!!! +============= +*/ +void D_AlphaSpans16 (espan_t *pspan) +{ + int count, spancount; + pixel_t *pbase, *pdest; + fixed16_t s, t, snext, tnext, sstep, tstep; + float sdivz, tdivz, zi, z, du, dv, spancountminus1; + float sdivz8stepu, tdivz8stepu, zi8stepu; + int izi, izistep; + short *pz; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + pbase = (unsigned char *)cacheblock; + + sdivz8stepu = d_sdivzstepu * 8; + tdivz8stepu = d_tdivzstepu * 8; + zi8stepu = d_zistepu * 8; + izistep = (int)(d_zistepu * 0x8000 * 0x10000); + + do + { + pdest = (d_viewbuffer + + (r_screenwidth * pspan->v) + pspan->u); + pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; + + count = pspan->count; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float)pspan->u; + dv = (float)pspan->v; + + sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; + tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; + zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; + izi = (int)(zi * 0x8000 * 0x10000); + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + + s = (int)(sdivz * z) + sadjust; + if (s > bbextents) + s = bbextents; + else if (s < 0) + s = 0; + + t = (int)(tdivz * z) + tadjust; + if (t > bbextentt) + t = bbextentt; + else if (t < 0) + t = 0; + + do + { + // calculate s and t at the far end of the span + if (count >= 8) + spancount = 8; + else + spancount = count; + + count -= spancount; + + if (count) + { + // calculate s/z, t/z, zi->fixed s and t at far end of span, + // calculate s and t steps across span by shifting + sdivz += sdivz8stepu; + tdivz += tdivz8stepu; + zi += zi8stepu; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on <0 steps + + sstep = (snext - s) >> 3; + tstep = (tnext - t) >> 3; + } + else + { + // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so + // can't step off polygon), clamp, calculate s and t steps across + // span by division, biasing steps low so we don't run off the + // texture + spancountminus1 = (float)(spancount - 1); + sdivz += d_sdivzstepu * spancountminus1; + tdivz += d_tdivzstepu * spancountminus1; + zi += d_zistepu * spancountminus1; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on <0 steps + + if (spancount > 1) + { + sstep = (snext - s) / (spancount - 1); + tstep = (tnext - t) / (spancount - 1); + } + } + + + // Drawing phrase + if (sw_texfilt->value == 0.0f) + { + do + { + pixel_t btemp; + + btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth); + if (btemp != TRANSPARENT_COLOR) + { + if (*pz <= (izi >> 16)) + { + *pdest = btemp; + *pz = izi >> 16; + } + } + pdest++; + pz++; + izi += izistep; + s += sstep; + t += tstep; + } while (--spancount > 0); + } + else if (sw_texfilt->value == 1.0f) + { + do + { + if (*pz <= (izi >> 16)) + { + int idiths = s; + int iditht = t; + + int X = (pspan->u + spancount) & 1; + int Y = (pspan->v)&1; + pixel_t btemp; + + //Using the kernel + idiths += kernel[X][Y][0]; + iditht += kernel[X][Y][1]; + + idiths = idiths >> 16; + idiths = idiths ? idiths -1 : idiths; + + + iditht = iditht >> 16; + iditht = iditht ? iditht -1 : iditht; + + + btemp = *(pbase + idiths + iditht * cachewidth); + if (btemp != TRANSPARENT_COLOR) + { + *pdest = btemp; + *pz = izi >> 16; + } + } + pdest++; + pz++; + s += sstep; + t += tstep; + } while (--spancount > 0); + } + + + } while (count > 0); + + } while ((pspan = pspan->pnext) != NULL); +} + + + +/* +============= +D_DrawSpans16 + + FIXME: actually make this subdivide by 16 instead of 8!!! +============= +*/ +void D_BlendSpans16 (espan_t *pspan, int alpha) +{ + int count, spancount; + pixel_t *pbase, *pdest; + fixed16_t s, t, snext, tnext, sstep, tstep; + float sdivz, tdivz, zi, z, du, dv, spancountminus1; + float sdivz8stepu, tdivz8stepu, zi8stepu; + int izi, izistep; + short *pz; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + pbase = (unsigned char *)cacheblock; + + sdivz8stepu = d_sdivzstepu * 8; + tdivz8stepu = d_tdivzstepu * 8; + zi8stepu = d_zistepu * 8; + izistep = (int)(d_zistepu * 0x8000 * 0x10000); + + do + { + pdest = (d_viewbuffer + + (r_screenwidth * pspan->v) + pspan->u); + pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; + + count = pspan->count; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float)pspan->u; + dv = (float)pspan->v; + + sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; + tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; + zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; + izi = (int)(zi * 0x8000 * 0x10000); + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + + s = (int)(sdivz * z) + sadjust; + if (s > bbextents) + s = bbextents; + else if (s < 0) + s = 0; + + t = (int)(tdivz * z) + tadjust; + if (t > bbextentt) + t = bbextentt; + else if (t < 0) + t = 0; + + do + { + // calculate s and t at the far end of the span + if (count >= 8) + spancount = 8; + else + spancount = count; + + count -= spancount; + + if (count) + { + // calculate s/z, t/z, zi->fixed s and t at far end of span, + // calculate s and t steps across span by shifting + sdivz += sdivz8stepu; + tdivz += tdivz8stepu; + zi += zi8stepu; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on <0 steps + + sstep = (snext - s) >> 3; + tstep = (tnext - t) >> 3; + } + else + { + // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so + // can't step off polygon), clamp, calculate s and t steps across + // span by division, biasing steps low so we don't run off the + // texture + spancountminus1 = (float)(spancount - 1); + sdivz += d_sdivzstepu * spancountminus1; + tdivz += d_tdivzstepu * spancountminus1; + zi += d_zistepu * spancountminus1; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on <0 steps + + if (spancount > 1) + { + sstep = (snext - s) / (spancount - 1); + tstep = (tnext - t) / (spancount - 1); + } + } + + + // Drawing phrase + if (sw_texfilt->value == 0.0f) + { + do + { + if (*pz <= (izi >> 16)) + { + pixel_t btemp; + + btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth); + + if( alpha != 7 ) + btemp = BLEND_ALPHA( alpha, btemp, *pdest); + *pdest = btemp; + //*pz = izi >> 16; + } + pdest++; + pz++; + izi += izistep; + s += sstep; + t += tstep; + } while (--spancount > 0); + } + else if (sw_texfilt->value == 1.0f) + { + do + { + int idiths = s; + int iditht = t; + + int X = (pspan->u + spancount) & 1; + int Y = (pspan->v)&1; + if (*pz <= (izi >> 16)) + { + pixel_t btemp; + + //Using the kernel + idiths += kernel[X][Y][0]; + iditht += kernel[X][Y][1]; + + idiths = idiths >> 16; + idiths = idiths ? idiths -1 : idiths; + + + iditht = iditht >> 16; + iditht = iditht ? iditht -1 : iditht; + + btemp = *(pbase + idiths + iditht * cachewidth); + + if( alpha != 7 ) + btemp = BLEND_ALPHA( alpha, btemp, *pdest); + *pdest = btemp; + //*pz = izi >> 16; + } + pdest++; + pz++; + izi += izistep; + s += sstep; + t += tstep; + } while (--spancount > 0); + } + + + } while (count > 0); + + } while ((pspan = pspan->pnext) != NULL); +} + #endif From d03d29f6f5ef48c80c247640cdc05b3797da6271 Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 3 Apr 2019 22:21:08 +0700 Subject: [PATCH 057/115] ref_soft: Fix transparency in API --- r_context.c | 2 +- r_local.h | 1 + r_triapi.c | 14 ++++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/r_context.c b/r_context.c index ceeede80..5b279706 100644 --- a/r_context.c +++ b/r_context.c @@ -592,7 +592,7 @@ ref_interface_t gReffuncs = TriBegin, TriEnd, _TriColor4f, - TriColor4ub, + _TriColor4ub, TriTexCoord2f, TriVertex3fv, TriVertex3f, diff --git a/r_local.h b/r_local.h index 9a500ae1..bef3d6d6 100644 --- a/r_local.h +++ b/r_local.h @@ -678,6 +678,7 @@ void TriVertex3fv( const float *v ); void TriVertex3f( float x, float y, float z ); void _TriColor4f( float r, float g, float b, float a ); void TriColor4ub( byte r, byte g, byte b, byte a ); +void _TriColor4ub( byte r, byte g, byte b, byte a ); int TriWorldToScreen( const float *world, float *screen ); int TriSpriteTexture( model_t *pSpriteModel, int frame ); void TriFog( float flFogColor[3], float flStart, float flEnd, int bOn ); diff --git a/r_triapi.c b/r_triapi.c index 8b61b38b..8402bca7 100644 --- a/r_triapi.c +++ b/r_triapi.c @@ -200,6 +200,20 @@ void TriColor4ub( byte r, byte g, byte b, byte a ) _TriColor4f( ds.triRGBA[0], ds.triRGBA[1], ds.triRGBA[2], 1.0f ); } +/* +============= +TriColor4ub + +============= +*/ +void _TriColor4ub( byte r, byte g, byte b, byte a ) +{ + _TriColor4f( r * (1.0f / 255.0f), + g * (1.0f / 255.0f), + b * (1.0f / 255.0f), + a * (1.0f / 255.0f)); +} + /* ================= TriColor4f From 8c9aa2588c3d0261cf9ed29d9a0b05b505bbcd85 Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 3 Apr 2019 22:55:46 +0700 Subject: [PATCH 058/115] ref_soft: Fix studio rendermodes, add additive brush rendermode --- r_edge.c | 3 + r_scan.c | 194 +++++++++++++++++++++++++++++++++++++++++++++++++++++ r_studio.c | 1 + 3 files changed, 198 insertions(+) diff --git a/r_edge.c b/r_edge.c index e20d3908..eec6f19f 100644 --- a/r_edge.c +++ b/r_edge.c @@ -985,6 +985,7 @@ qboolean alphaspans; void D_AlphaSpans16 (espan_t *pspan); +void D_AddSpans16 (espan_t *pspan); void D_BlendSpans16 (espan_t *pspan, int alpha ); void TurbulentZ8 (espan_t *pspan, int alpha ); /* @@ -1072,6 +1073,8 @@ void D_AlphaSurf (surf_t *s) if( RI.currententity->curstate.rendermode == kRenderTransAlpha ) D_AlphaSpans16(s->spans); + else if( RI.currententity->curstate.rendermode == kRenderTransAdd ) + D_AddSpans16(s->spans); else D_BlendSpans16(s->spans, RI.currententity->curstate.renderamt * 7 / 255 ); } diff --git a/r_scan.c b/r_scan.c index 8a31b90e..77d151ed 100644 --- a/r_scan.c +++ b/r_scan.c @@ -1134,6 +1134,200 @@ void D_BlendSpans16 (espan_t *pspan, int alpha) } while ((pspan = pspan->pnext) != NULL); } + + +/* +============= +D_DrawSpans16 + + FIXME: actually make this subdivide by 16 instead of 8!!! +============= +*/ +void D_AddSpans16 (espan_t *pspan) +{ + int count, spancount; + pixel_t *pbase, *pdest; + fixed16_t s, t, snext, tnext, sstep, tstep; + float sdivz, tdivz, zi, z, du, dv, spancountminus1; + float sdivz8stepu, tdivz8stepu, zi8stepu; + int izi, izistep; + short *pz; + + sstep = 0; // keep compiler happy + tstep = 0; // ditto + + pbase = (unsigned char *)cacheblock; + + sdivz8stepu = d_sdivzstepu * 8; + tdivz8stepu = d_tdivzstepu * 8; + zi8stepu = d_zistepu * 8; + izistep = (int)(d_zistepu * 0x8000 * 0x10000); + + do + { + pdest = (d_viewbuffer + + (r_screenwidth * pspan->v) + pspan->u); + pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; + + count = pspan->count; + + // calculate the initial s/z, t/z, 1/z, s, and t and clamp + du = (float)pspan->u; + dv = (float)pspan->v; + + sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; + tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; + zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; + izi = (int)(zi * 0x8000 * 0x10000); + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + + s = (int)(sdivz * z) + sadjust; + if (s > bbextents) + s = bbextents; + else if (s < 0) + s = 0; + + t = (int)(tdivz * z) + tadjust; + if (t > bbextentt) + t = bbextentt; + else if (t < 0) + t = 0; + + do + { + // calculate s and t at the far end of the span + if (count >= 8) + spancount = 8; + else + spancount = count; + + count -= spancount; + + if (count) + { + // calculate s/z, t/z, zi->fixed s and t at far end of span, + // calculate s and t steps across span by shifting + sdivz += sdivz8stepu; + tdivz += tdivz8stepu; + zi += zi8stepu; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on <0 steps + + sstep = (snext - s) >> 3; + tstep = (tnext - t) >> 3; + } + else + { + // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so + // can't step off polygon), clamp, calculate s and t steps across + // span by division, biasing steps low so we don't run off the + // texture + spancountminus1 = (float)(spancount - 1); + sdivz += d_sdivzstepu * spancountminus1; + tdivz += d_tdivzstepu * spancountminus1; + zi += d_zistepu * spancountminus1; + z = (float)0x10000 / zi; // prescale to 16.16 fixed-point + snext = (int)(sdivz * z) + sadjust; + if (snext > bbextents) + snext = bbextents; + else if (snext < 8) + snext = 8; // prevent round-off error on <0 steps from + // from causing overstepping & running off the + // edge of the texture + + tnext = (int)(tdivz * z) + tadjust; + if (tnext > bbextentt) + tnext = bbextentt; + else if (tnext < 8) + tnext = 8; // guard against round-off error on <0 steps + + if (spancount > 1) + { + sstep = (snext - s) / (spancount - 1); + tstep = (tnext - t) / (spancount - 1); + } + } + + + // Drawing phrase + if (sw_texfilt->value == 0.0f) + { + do + { + if (*pz <= (izi >> 16)) + { + pixel_t btemp; + + btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth); + + btemp = BLEND_ADD( btemp, *pdest); + *pdest = btemp; + //*pz = izi >> 16; + } + pdest++; + pz++; + izi += izistep; + s += sstep; + t += tstep; + } while (--spancount > 0); + } + else if (sw_texfilt->value == 1.0f) + { + do + { + int idiths = s; + int iditht = t; + + int X = (pspan->u + spancount) & 1; + int Y = (pspan->v)&1; + if (*pz <= (izi >> 16)) + { + pixel_t btemp; + + //Using the kernel + idiths += kernel[X][Y][0]; + iditht += kernel[X][Y][1]; + + idiths = idiths >> 16; + idiths = idiths ? idiths -1 : idiths; + + + iditht = iditht >> 16; + iditht = iditht ? iditht -1 : iditht; + + btemp = *(pbase + idiths + iditht * cachewidth); + + btemp = BLEND_ADD( btemp, *pdest); + *pdest = btemp; + //*pz = izi >> 16; + } + pdest++; + pz++; + izi += izistep; + s += sstep; + t += tstep; + } while (--spancount > 0); + } + + + } while (count > 0); + + } while ((pspan = pspan->pnext) != NULL); +} + #endif diff --git a/r_studio.c b/r_studio.c index 64b653ea..584acbe2 100644 --- a/r_studio.c +++ b/r_studio.c @@ -2786,6 +2786,7 @@ set rendermode for studiomodel */ void GL_StudioSetRenderMode( int rendermode ) { + GL_SetRenderMode( rendermode ); #if 0 switch( rendermode ) { From c52453faa3ee1dc69e25c9adf442e053599e5fc8 Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 3 Apr 2019 23:01:25 +0700 Subject: [PATCH 059/115] ref_soft: Remove r_poly --- r_local.h | 20 - r_poly.c | 1276 ----------------------------------------------------- 2 files changed, 1296 deletions(-) delete mode 100644 r_poly.c diff --git a/r_local.h b/r_local.h index bef3d6d6..d3a6610d 100644 --- a/r_local.h +++ b/r_local.h @@ -1024,21 +1024,6 @@ typedef struct espan_s struct espan_s *pnext; } espan_t; -// used by the polygon drawer (R_POLY.C) and sprite setup code (R_SPRITE.C) -typedef struct -{ - int nump; - emitpoint_t *pverts; - pixel_t *pixels; // image - int pixel_width; // image width - int pixel_height; // image height - vec3_t vup, vright, vpn; // in worldspace, for plane eq - float dist; - float s_offset, t_offset; - float viewer_position[3]; - void (*drawspanlet)( void ); - int stipple_parity; -} polydesc_t; // FIXME: compress, make a union if that will help // insubmodel is only 1, flags is fewer than 32, spanstate could be a byte @@ -1331,11 +1316,6 @@ void R_SetupFinalVert( finalvert_t *fv, float x, float y, float z, int light, in void RotatedBBox (vec3_t mins, vec3_t maxs, vec3_t angles, vec3_t tmins, vec3_t tmaxs); int R_BmodelCheckBBox (float *minmaxs); -// -// r_poly.c -// -void R_BuildPolygonFromSurface(msurface_t *fa); -void R_ClipAndDrawPoly( float alpha, qboolean isturbulent, qboolean textured ); void R_SetUpWorldTransform (void); diff --git a/r_poly.c b/r_poly.c deleted file mode 100644 index 0c7a1f9b..00000000 --- a/r_poly.c +++ /dev/null @@ -1,1276 +0,0 @@ -/* -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. - -*/ -#include -#include "r_local.h" - -#define AFFINE_SPANLET_SIZE 16 -#define AFFINE_SPANLET_SIZE_BITS 4 - -typedef struct -{ - int sent1; - pixel_t *pbase, *pdest; - short *pz; - int sent3; - fixed16_t s, t; - fixed16_t sstep, tstep; - int izi, izistep, izistep_times_2; - int spancount; - unsigned u, v; - int sent2; -} spanletvars_t; - -spanletvars_t s_spanletvars; - -//static int r_polyblendcolor; - -static espan_t *s_polygon_spans; - -polydesc_t r_polydesc; - -msurface_t *r_alpha_surfaces; - -extern int *r_turb_turb; - -static int clip_current; -typedef vec_t vec5_t[5]; -vec5_t r_clip_verts[2][MAXWORKINGVERTS+2]; - -static int s_minindex, s_maxindex; - -static void R_DrawPoly( qboolean iswater ); - -/* -** R_DrawSpanletOpaque -*/ -void R_DrawSpanletOpaque( void ) -{ - pixel_t btemp; - - do - { - unsigned ts, tt; - - ts = s_spanletvars.s >> 16; - tt = s_spanletvars.t >> 16; - - btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth); - if (btemp != TRANSPARENT_COLOR) - { - if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16)) - { - *s_spanletvars.pz = s_spanletvars.izi >> 16; - *s_spanletvars.pdest = btemp; - } - } - - s_spanletvars.izi += s_spanletvars.izistep; - s_spanletvars.pdest++; - s_spanletvars.pz++; - s_spanletvars.s += s_spanletvars.sstep; - s_spanletvars.t += s_spanletvars.tstep; - } while (--s_spanletvars.spancount > 0); -} - -/* -** R_DrawSpanletTurbulentStipple33 -*/ -void R_DrawSpanletTurbulentStipple33( void ) -{ - pixel_t btemp; - int sturb, tturb; - pixel_t *pdest = s_spanletvars.pdest; - short *pz = s_spanletvars.pz; - int izi = s_spanletvars.izi; - - if ( s_spanletvars.v & 1 ) - { - s_spanletvars.pdest += s_spanletvars.spancount; - s_spanletvars.pz += s_spanletvars.spancount; - - if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE ) - s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS; - else - s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep; - - if ( s_spanletvars.u & 1 ) - { - izi += s_spanletvars.izistep; - s_spanletvars.s += s_spanletvars.sstep; - s_spanletvars.t += s_spanletvars.tstep; - - pdest++; - pz++; - s_spanletvars.spancount--; - } - - s_spanletvars.sstep *= 2; - s_spanletvars.tstep *= 2; - - while ( s_spanletvars.spancount > 0 ) - { - sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63; - tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63; - - btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) ); - - if ( *pz <= ( izi >> 16 ) ) - *pdest = btemp; - - izi += s_spanletvars.izistep_times_2; - s_spanletvars.s += s_spanletvars.sstep; - s_spanletvars.t += s_spanletvars.tstep; - - pdest += 2; - pz += 2; - - s_spanletvars.spancount -= 2; - } - } -} - -/* -** R_DrawSpanletTurbulentStipple66 -*/ -void R_DrawSpanletTurbulentStipple66( void ) -{ - pixel_t btemp; - int sturb, tturb; - pixel_t *pdest = s_spanletvars.pdest; - short *pz = s_spanletvars.pz; - int izi = s_spanletvars.izi; - - if ( !( s_spanletvars.v & 1 ) ) - { - s_spanletvars.pdest += s_spanletvars.spancount; - s_spanletvars.pz += s_spanletvars.spancount; - - if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE ) - s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS; - else - s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep; - - if ( s_spanletvars.u & 1 ) - { - izi += s_spanletvars.izistep; - s_spanletvars.s += s_spanletvars.sstep; - s_spanletvars.t += s_spanletvars.tstep; - - pdest++; - pz++; - s_spanletvars.spancount--; - } - - s_spanletvars.sstep *= 2; - s_spanletvars.tstep *= 2; - - while ( s_spanletvars.spancount > 0 ) - { - sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63; - tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63; - - btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) ); - - if ( *pz <= ( izi >> 16 ) ) - *pdest = btemp; - - izi += s_spanletvars.izistep_times_2; - s_spanletvars.s += s_spanletvars.sstep; - s_spanletvars.t += s_spanletvars.tstep; - - pdest += 2; - pz += 2; - - s_spanletvars.spancount -= 2; - } - } - else - { - s_spanletvars.pdest += s_spanletvars.spancount; - s_spanletvars.pz += s_spanletvars.spancount; - - if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE ) - s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS; - else - s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep; - - while ( s_spanletvars.spancount > 0 ) - { - sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63; - tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63; - - btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) ); - - if ( *pz <= ( izi >> 16 ) ) - *pdest = btemp; - - izi += s_spanletvars.izistep; - s_spanletvars.s += s_spanletvars.sstep; - s_spanletvars.t += s_spanletvars.tstep; - - pdest++; - pz++; - - s_spanletvars.spancount--; - } - } -} - -/* -** R_DrawSpanletTurbulentBlended -*/ -void R_DrawSpanletTurbulentBlended66( void ) -{ - pixel_t btemp; - int sturb, tturb; - - do - { - sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63; - tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63; - - btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) ); - - if ( *s_spanletvars.pz <= ( s_spanletvars.izi >> 16 ) ) - { - pixel_t screen = *s_spanletvars.pdest; - pixel_t src = btemp; - byte alpha = 5; - *s_spanletvars.pdest = BLEND_ALPHA( alpha, src, screen);//vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff)); - } - - s_spanletvars.izi += s_spanletvars.izistep; - s_spanletvars.pdest++; - s_spanletvars.pz++; - s_spanletvars.s += s_spanletvars.sstep; - s_spanletvars.t += s_spanletvars.tstep; - - } while ( --s_spanletvars.spancount > 0 ); -} - -void R_DrawSpanletTurbulentBlended33( void ) -{ - pixel_t btemp; - int sturb, tturb; - - do - { - sturb = ((s_spanletvars.s + r_turb_turb[(s_spanletvars.t>>16)&(CYCLE-1)])>>16)&63; - tturb = ((s_spanletvars.t + r_turb_turb[(s_spanletvars.s>>16)&(CYCLE-1)])>>16)&63; - - btemp = *( s_spanletvars.pbase + ( sturb ) + ( tturb << 6 ) ); - - if ( *s_spanletvars.pz <= ( s_spanletvars.izi >> 16 ) ) - { - pixel_t screen = *s_spanletvars.pdest; - pixel_t src = btemp; - byte alpha = 2; - *s_spanletvars.pdest = BLEND_ALPHA( alpha, src, screen); - } - - s_spanletvars.izi += s_spanletvars.izistep; - s_spanletvars.pdest++; - s_spanletvars.pz++; - s_spanletvars.s += s_spanletvars.sstep; - s_spanletvars.t += s_spanletvars.tstep; - - } while ( --s_spanletvars.spancount > 0 ); -} - -/* -** R_DrawSpanlet33 -*/ -void R_DrawSpanlet33( void ) -{ - pixel_t btemp; - - do - { - unsigned ts, tt; - - ts = s_spanletvars.s >> 16; - tt = s_spanletvars.t >> 16; - - btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth); - - if ( btemp != TRANSPARENT_COLOR ) - { - if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16)) - { - pixel_t screen = *s_spanletvars.pdest; - pixel_t src = btemp; - byte alpha = 2; - *s_spanletvars.pdest = BLEND_ALPHA( alpha, src, screen); - } - - } - - s_spanletvars.izi += s_spanletvars.izistep; - s_spanletvars.pdest++; - s_spanletvars.pz++; - s_spanletvars.s += s_spanletvars.sstep; - s_spanletvars.t += s_spanletvars.tstep; - } while (--s_spanletvars.spancount > 0); -} - -void R_DrawSpanletConstant33( void ) -{ - do - { - if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16)) - { - //*s_spanletvars.pdest = BLEND_ALPHA( alpha, src, screen); - } - - s_spanletvars.izi += s_spanletvars.izistep; - s_spanletvars.pdest++; - s_spanletvars.pz++; - } while (--s_spanletvars.spancount > 0); -} - -/* -** R_DrawSpanlet66 -*/ -void R_DrawSpanlet66( void ) -{ - pixel_t btemp; - - do - { - unsigned ts, tt; - - ts = s_spanletvars.s >> 16; - tt = s_spanletvars.t >> 16; - - btemp = *(s_spanletvars.pbase + (ts) + (tt) * cachewidth); - - if ( btemp != TRANSPARENT_COLOR ) - { - if (*s_spanletvars.pz <= (s_spanletvars.izi >> 16)) - { - pixel_t screen = *s_spanletvars.pdest; - pixel_t src = btemp; - byte alpha = 5; - *s_spanletvars.pdest = BLEND_ALPHA( alpha, src, screen); - } - - } - - s_spanletvars.izi += s_spanletvars.izistep; - s_spanletvars.pdest++; - s_spanletvars.pz++; - s_spanletvars.s += s_spanletvars.sstep; - s_spanletvars.t += s_spanletvars.tstep; - } while (--s_spanletvars.spancount > 0); -} - -/* -** R_DrawSpanlet33Stipple -*/ -void R_DrawSpanlet33Stipple( void ) -{ - pixel_t btemp; - pixel_t *pdest = s_spanletvars.pdest; - short *pz = s_spanletvars.pz; - int izi = s_spanletvars.izi; - - if ( r_polydesc.stipple_parity ^ ( s_spanletvars.v & 1 ) ) - { - s_spanletvars.pdest += s_spanletvars.spancount; - s_spanletvars.pz += s_spanletvars.spancount; - - if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE ) - s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS; - else - s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep; - - if ( r_polydesc.stipple_parity ^ ( s_spanletvars.u & 1 ) ) - { - izi += s_spanletvars.izistep; - s_spanletvars.s += s_spanletvars.sstep; - s_spanletvars.t += s_spanletvars.tstep; - - pdest++; - pz++; - s_spanletvars.spancount--; - } - - s_spanletvars.sstep *= 2; - s_spanletvars.tstep *= 2; - - while ( s_spanletvars.spancount > 0 ) - { - unsigned s = s_spanletvars.s >> 16; - unsigned t = s_spanletvars.t >> 16; - - btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) ); - - if ( btemp != TRANSPARENT_COLOR ) - { - if ( *pz <= ( izi >> 16 ) ) - *pdest = btemp; - } - - izi += s_spanletvars.izistep_times_2; - s_spanletvars.s += s_spanletvars.sstep; - s_spanletvars.t += s_spanletvars.tstep; - - pdest += 2; - pz += 2; - - s_spanletvars.spancount -= 2; - } - } -} - -/* -** R_DrawSpanlet66Stipple -*/ -void R_DrawSpanlet66Stipple( void ) -{ - pixel_t btemp; - pixel_t *pdest = s_spanletvars.pdest; - short *pz = s_spanletvars.pz; - int izi = s_spanletvars.izi; - - s_spanletvars.pdest += s_spanletvars.spancount; - s_spanletvars.pz += s_spanletvars.spancount; - - if ( s_spanletvars.spancount == AFFINE_SPANLET_SIZE ) - s_spanletvars.izi += s_spanletvars.izistep << AFFINE_SPANLET_SIZE_BITS; - else - s_spanletvars.izi += s_spanletvars.izistep * s_spanletvars.izistep; - - if ( r_polydesc.stipple_parity ^ ( s_spanletvars.v & 1 ) ) - { - if ( r_polydesc.stipple_parity ^ ( s_spanletvars.u & 1 ) ) - { - izi += s_spanletvars.izistep; - s_spanletvars.s += s_spanletvars.sstep; - s_spanletvars.t += s_spanletvars.tstep; - - pdest++; - pz++; - s_spanletvars.spancount--; - } - - s_spanletvars.sstep *= 2; - s_spanletvars.tstep *= 2; - - while ( s_spanletvars.spancount > 0 ) - { - unsigned s = s_spanletvars.s >> 16; - unsigned t = s_spanletvars.t >> 16; - - btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) ); - - if ( btemp != TRANSPARENT_COLOR ) - { - if ( *pz <= ( izi >> 16 ) ) - *pdest = btemp; - } - - izi += s_spanletvars.izistep_times_2; - s_spanletvars.s += s_spanletvars.sstep; - s_spanletvars.t += s_spanletvars.tstep; - - pdest += 2; - pz += 2; - - s_spanletvars.spancount -= 2; - } - } - else - { - while ( s_spanletvars.spancount > 0 ) - { - unsigned s = s_spanletvars.s >> 16; - unsigned t = s_spanletvars.t >> 16; - - btemp = *( s_spanletvars.pbase + ( s ) + ( t * cachewidth ) ); - - if ( btemp != TRANSPARENT_COLOR ) - { - if ( *pz <= ( izi >> 16 ) ) - *pdest = btemp; - } - - izi += s_spanletvars.izistep; - s_spanletvars.s += s_spanletvars.sstep; - s_spanletvars.t += s_spanletvars.tstep; - - pdest++; - pz++; - - s_spanletvars.spancount--; - } - } -} - -/* -** R_ClipPolyFace -** -** Clips the winding at clip_verts[clip_current] and changes clip_current -** Throws out the back side -*/ -int R_ClipPolyFace (int nump, clipplane_t *pclipplane) -{ - int i, outcount; - float dists[MAXWORKINGVERTS+3]; - float frac, clipdist, *pclipnormal; - float *in, *instep, *outstep, *vert2; - - clipdist = pclipplane->dist; - pclipnormal = pclipplane->normal; - -// calc dists - if (clip_current) - { - in = r_clip_verts[1][0]; - outstep = r_clip_verts[0][0]; - clip_current = 0; - } - else - { - in = r_clip_verts[0][0]; - outstep = r_clip_verts[1][0]; - clip_current = 1; - } - - instep = in; - for (i=0 ; i= 0) - { - memcpy (outstep, instep, sizeof (vec5_t)); - outstep += sizeof (vec5_t) / sizeof (float); - outcount++; - } - - if (dists[i] == 0 || dists[i+1] == 0) - continue; - - if ( (dists[i] > 0) == (dists[i+1] > 0) ) - continue; - - // split it into a new vertex - frac = dists[i] / (dists[i] - dists[i+1]); - - vert2 = instep + sizeof (vec5_t) / sizeof (float); - - outstep[0] = instep[0] + frac*(vert2[0] - instep[0]); - outstep[1] = instep[1] + frac*(vert2[1] - instep[1]); - outstep[2] = instep[2] + frac*(vert2[2] - instep[2]); - outstep[3] = instep[3] + frac*(vert2[3] - instep[3]); - outstep[4] = instep[4] + frac*(vert2[4] - instep[4]); - - outstep += sizeof (vec5_t) / sizeof (float); - outcount++; - } - - return outcount; -} - -/* -** R_PolygonDrawSpans -*/ -void R_PolygonDrawSpans(espan_t *pspan, qboolean iswater ) -{ - int count; - fixed16_t snext, tnext; - float sdivz, tdivz, zi, z, du, dv, spancountminus1; - float sdivzspanletstepu, tdivzspanletstepu, zispanletstepu; - - s_spanletvars.pbase = cacheblock; - - if ( iswater ) - r_turb_turb = sintable + ((int)(gpGlobals->time*SPEED)&(CYCLE-1)); - - sdivzspanletstepu = d_sdivzstepu * AFFINE_SPANLET_SIZE; - tdivzspanletstepu = d_tdivzstepu * AFFINE_SPANLET_SIZE; - zispanletstepu = d_zistepu * AFFINE_SPANLET_SIZE; - -// we count on FP exceptions being turned off to avoid range problems - s_spanletvars.izistep = (int)(d_zistepu * 0x8000 * 0x10000); - s_spanletvars.izistep_times_2 = s_spanletvars.izistep * 2; - - s_spanletvars.pz = 0; - - do - { - s_spanletvars.pdest = d_viewbuffer + ( d_scantable[pspan->v] /*r_screenwidth * pspan->v*/) + pspan->u; - s_spanletvars.pz = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u; - s_spanletvars.u = pspan->u; - s_spanletvars.v = pspan->v; - //printf("%p %p %d %d\n", s_spanletvars.pdest, s_spanletvars.pz, s_spanletvars.u, s_spanletvars.v); - - count = pspan->count; - - if (count <= 0) - goto NextSpan; - - // calculate the initial s/z, t/z, 1/z, s, and t and clamp - du = (float)pspan->u; - dv = (float)pspan->v; - - sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; - tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; - - zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; - z = (float)0x10000 / zi; // prescale to 16.16 fixed-point - // we count on FP exceptions being turned off to avoid range problems - s_spanletvars.izi = (int)(zi * 0x8000 * 0x10000); - - s_spanletvars.s = (int)(sdivz * z) + sadjust; - s_spanletvars.t = (int)(tdivz * z) + tadjust; - - if ( !iswater ) - { - if (s_spanletvars.s > bbextents) - s_spanletvars.s = bbextents; - else if (s_spanletvars.s < 0) - s_spanletvars.s = 0; - - if (s_spanletvars.t > bbextentt) - s_spanletvars.t = bbextentt; - else if (s_spanletvars.t < 0) - s_spanletvars.t = 0; - } - - do - { - // calculate s and t at the far end of the span - if (count >= AFFINE_SPANLET_SIZE ) - s_spanletvars.spancount = AFFINE_SPANLET_SIZE; - else - s_spanletvars.spancount = count; - - count -= s_spanletvars.spancount; - - if (count) - { - // calculate s/z, t/z, zi->fixed s and t at far end of span, - // calculate s and t steps across span by shifting - sdivz += sdivzspanletstepu; - tdivz += tdivzspanletstepu; - zi += zispanletstepu; - z = (float)0x10000 / zi; // prescale to 16.16 fixed-point - - snext = (int)(sdivz * z) + sadjust; - tnext = (int)(tdivz * z) + tadjust; - - if ( !iswater ) - { - if (snext > bbextents) - snext = bbextents; - else if (snext < AFFINE_SPANLET_SIZE) - snext = AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from - // from causing overstepping & running off the - // edge of the texture - - if (tnext > bbextentt) - tnext = bbextentt; - else if (tnext < AFFINE_SPANLET_SIZE) - tnext = AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps - } - - s_spanletvars.sstep = (snext - s_spanletvars.s) >> AFFINE_SPANLET_SIZE_BITS; - s_spanletvars.tstep = (tnext - s_spanletvars.t) >> AFFINE_SPANLET_SIZE_BITS; - } - else - { - // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so - // can't step off polygon), clamp, calculate s and t steps across - // span by division, biasing steps low so we don't run off the - // texture - spancountminus1 = (float)(s_spanletvars.spancount - 1); - sdivz += d_sdivzstepu * spancountminus1; - tdivz += d_tdivzstepu * spancountminus1; - zi += d_zistepu * spancountminus1; - z = (float)0x10000 / zi; // prescale to 16.16 fixed-point - snext = (int)(sdivz * z) + sadjust; - tnext = (int)(tdivz * z) + tadjust; - - if ( !iswater ) - { - if (snext > bbextents) - snext = bbextents; - else if (snext < AFFINE_SPANLET_SIZE) - snext = AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from - // from causing overstepping & running off the - // edge of the texture - - if (tnext > bbextentt) - tnext = bbextentt; - else if (tnext < AFFINE_SPANLET_SIZE) - tnext = AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps - } - - if (s_spanletvars.spancount > 1) - { - s_spanletvars.sstep = (snext - s_spanletvars.s) / (s_spanletvars.spancount - 1); - s_spanletvars.tstep = (tnext - s_spanletvars.t) / (s_spanletvars.spancount - 1); - } - } - - if ( iswater ) - { - s_spanletvars.s = s_spanletvars.s & ((CYCLE<<16)-1); - s_spanletvars.t = s_spanletvars.t & ((CYCLE<<16)-1); - } - - r_polydesc.drawspanlet(); - - s_spanletvars.s = snext; - s_spanletvars.t = tnext; - - } while (count > 0); - -NextSpan: - pspan++; - - } while (pspan->count != DS_SPAN_LIST_END); -} - -/* -** -** R_PolygonScanLeftEdge -** -** Goes through the polygon and scans the left edge, filling in -** screen coordinate data for the spans -*/ -void R_PolygonScanLeftEdge (void) -{ - int i, v, itop, ibottom, lmaxindex; - emitpoint_t *pvert, *pnext; - espan_t *pspan; - float du, dv, vtop, vbottom, slope; - fixed16_t u, u_step; - - pspan = s_polygon_spans; - i = s_minindex; - if (i == 0) - i = r_polydesc.nump; - - lmaxindex = s_maxindex; - if (lmaxindex == 0) - lmaxindex = r_polydesc.nump; - - vtop = ceil (r_polydesc.pverts[i].v); - - do - { - pvert = &r_polydesc.pverts[i]; - pnext = pvert - 1; - - vbottom = ceil (pnext->v); - - if (vtop < vbottom) - { - du = pnext->u - pvert->u; - dv = pnext->v - pvert->v; - - slope = du / dv; - u_step = (int)(slope * 0x10000); - // adjust u to ceil the integer portion - u = (int)((pvert->u + (slope * (vtop - pvert->v))) * 0x10000) + - (0x10000 - 1); - itop = (int)vtop; - ibottom = (int)vbottom; - - for (v=itop ; vu = u >> 16; - pspan->v = v; - u += u_step; - pspan++; - } - } - - vtop = vbottom; - - i--; - if (i == 0) - i = r_polydesc.nump; - - } while (i != lmaxindex); -} - -/* -** R_PolygonScanRightEdge -** -** Goes through the polygon and scans the right edge, filling in -** count values. -*/ -void R_PolygonScanRightEdge (void) -{ - int i, v, itop, ibottom; - emitpoint_t *pvert, *pnext; - espan_t *pspan; - float du, dv, vtop, vbottom, slope, uvert, unext, vvert, vnext; - fixed16_t u, u_step; - - pspan = s_polygon_spans; - i = s_minindex; - - vvert = r_polydesc.pverts[i].v; - if (vvert < RI.fvrecty_adj) - vvert = RI.fvrecty_adj; - if (vvert > RI.fvrectbottom_adj) - vvert = RI.fvrectbottom_adj; - - vtop = ceil (vvert); - - do - { - pvert = &r_polydesc.pverts[i]; - pnext = pvert + 1; - - vnext = pnext->v; - if (vnext < RI.fvrecty_adj) - vnext = RI.fvrecty_adj; - if (vnext > RI.fvrectbottom_adj) - vnext = RI.fvrectbottom_adj; - - vbottom = ceil (vnext); - - if (vtop < vbottom) - { - uvert = pvert->u; - if (uvert < RI.fvrectx_adj) - uvert = RI.fvrectx_adj; - if (uvert > RI.fvrectright_adj) - uvert = RI.fvrectright_adj; - - unext = pnext->u; - if (unext < RI.fvrectx_adj) - unext = RI.fvrectx_adj; - if (unext > RI.fvrectright_adj) - unext = RI.fvrectright_adj; - - du = unext - uvert; - dv = vnext - vvert; - slope = du / dv; - u_step = (int)(slope * 0x10000); - // adjust u to ceil the integer portion - u = (int)((uvert + (slope * (vtop - vvert))) * 0x10000) + - (0x10000 - 1); - itop = (int)vtop; - ibottom = (int)vbottom; - - for (v=itop ; vcount = (u >> 16) - pspan->u; - u += u_step; - pspan++; - } - } - - vtop = vbottom; - vvert = vnext; - - i++; - if (i == r_polydesc.nump) - i = 0; - - } while (i != s_maxindex); - - pspan->count = DS_SPAN_LIST_END; // mark the end of the span list -} - -/* -** R_ClipAndDrawPoly -*/ -void R_ClipAndDrawPoly( float alpha, qboolean isturbulent, qboolean textured ) -{ - emitpoint_t outverts[MAXWORKINGVERTS+3], *pout; - float *pv; - int i, nump; - float scale; - vec3_t transformed, local; - - if ( !textured ) - { - r_polydesc.drawspanlet = R_DrawSpanletConstant33; - } - else - { - - /* - ** choose the correct spanlet routine based on alpha - */ - if ( alpha == 1 ) - { - // isturbulent is ignored because we know that turbulent surfaces - // can't be opaque - r_polydesc.drawspanlet = R_DrawSpanletOpaque; - } - else - { - if ( sw_stipplealpha->value ) - { - if ( isturbulent ) - { - if ( alpha > 0.33 ) - r_polydesc.drawspanlet = R_DrawSpanletTurbulentStipple66; - else - r_polydesc.drawspanlet = R_DrawSpanletTurbulentStipple33; - } - else - { - if ( alpha > 0.33 ) - r_polydesc.drawspanlet = R_DrawSpanlet66Stipple; - else - r_polydesc.drawspanlet = R_DrawSpanlet33Stipple; - } - } - else - { - if ( isturbulent ) - { - if ( alpha > 0.33 ) - r_polydesc.drawspanlet = R_DrawSpanletTurbulentBlended66; - else - r_polydesc.drawspanlet = R_DrawSpanletTurbulentBlended33; - } - else - { - if ( alpha > 0.33 ) - r_polydesc.drawspanlet = R_DrawSpanlet66; - else - r_polydesc.drawspanlet = R_DrawSpanlet33; - } - } - } - } - - // clip to the frustum in worldspace - nump = r_polydesc.nump; - clip_current = 0; - - for (i=0 ; i<4 ; i++) - { - nump = R_ClipPolyFace (nump, &view_clipplanes[i]); - if (nump < 3) - return; - if (nump > MAXWORKINGVERTS) - gEngfuncs.Host_Error( "R_ClipAndDrawPoly: too many points: %d", nump ); - } - -// transform vertices into viewspace and project - pv = &r_clip_verts[clip_current][0][0]; - - for (i=0 ; izi = 1.0 / transformed[2]; - - pout->s = pv[3]; - pout->t = pv[4]; - - scale = xscale * pout->zi; - pout->u = (xcenter + scale * transformed[0]); - - scale = yscale * pout->zi; - pout->v = (ycenter - scale * transformed[1]); - - pv += sizeof (vec5_t) / sizeof (pv); - } - -// draw it - r_polydesc.nump = nump; - r_polydesc.pverts = outverts; - - R_DrawPoly( isturbulent ); -} - -/* -** R_BuildPolygonFromSurface -*/ -void R_BuildPolygonFromSurface(msurface_t *fa) -{ - int i, lindex, lnumverts; - medge_t *pedges, *r_pedge; - int vertpage; - float *vec; - vec5_t *pverts; - float tmins[2] = { 0, 0 }; - - r_polydesc.nump = 0; - - // reconstruct the polygon - pedges = RI.currentmodel->edges; - lnumverts = fa->numedges; - vertpage = 0; - - pverts = r_clip_verts[0]; - - for (i=0 ; isurfedges[fa->firstedge + i]; - - if (lindex > 0) - { - r_pedge = &pedges[lindex]; - vec = RI.currentmodel->vertexes[r_pedge->v[0]].position; - } - else - { - r_pedge = &pedges[-lindex]; - vec = RI.currentmodel->vertexes[r_pedge->v[1]].position; - } - - VectorAdd (vec, r_entorigin, pverts[i] ); - //VectorCopy( vec, pverts[i] ); - } - - VectorCopy( fa->texinfo->vecs[0], r_polydesc.vright ); - VectorCopy( fa->texinfo->vecs[1], r_polydesc.vup ); - VectorCopy( fa->plane->normal, r_polydesc.vpn ); - VectorCopy( modelorg, r_polydesc.viewer_position ); - - - if ( fa->flags & SURF_PLANEBACK ) - { - VectorSubtract( vec3_origin, r_polydesc.vpn, r_polydesc.vpn ); - } - - // todo: water - if ( fa->flags & SURF_DRAWTURB ) - { - image_t *pic = R_GetTexture(fa->texinfo->texture->gl_texturenum); - r_polydesc.pixels = pic->pixels[0]; - r_polydesc.pixel_width = pic->width; - r_polydesc.pixel_height = pic->height; - } - else - { - surfcache_t *scache; - - scache = D_CacheSurface( fa, 0 ); - - r_polydesc.pixels = scache->data; - r_polydesc.pixel_width = scache->width; - r_polydesc.pixel_height = scache->height; - - tmins[0] = fa->texturemins[0]; - tmins[1] = fa->texturemins[1]; - } - - r_polydesc.dist = DotProduct( r_polydesc.vpn, pverts[0] ); - - r_polydesc.s_offset = fa->texinfo->vecs[0][3] - tmins[0]; - r_polydesc.t_offset = fa->texinfo->vecs[1][3] - tmins[1]; - - // scrolling texture addition - // todo: conveyors - if (fa->flags & SURF_CONVEYOR) - { - r_polydesc.s_offset += -128 * ( (gpGlobals->time*0.25) - (int)(gpGlobals->time*0.25) ); - } - - r_polydesc.nump = lnumverts; -} - -/* -** R_PolygonCalculateGradients -*/ -void R_PolygonCalculateGradients (void) -{ - vec3_t p_normal, p_saxis, p_taxis; - float distinv; - - TransformVector (r_polydesc.vpn, p_normal); - TransformVector (r_polydesc.vright, p_saxis); - TransformVector (r_polydesc.vup, p_taxis); - - distinv = 1.0 / (-(DotProduct (r_polydesc.viewer_position, r_polydesc.vpn)) + r_polydesc.dist ); - - d_sdivzstepu = p_saxis[0] * xscaleinv; - d_sdivzstepv = -p_saxis[1] * yscaleinv; - d_sdivzorigin = p_saxis[2] - xcenter * d_sdivzstepu - ycenter * d_sdivzstepv; - - d_tdivzstepu = p_taxis[0] * xscaleinv; - d_tdivzstepv = -p_taxis[1] * yscaleinv; - d_tdivzorigin = p_taxis[2] - xcenter * d_tdivzstepu - ycenter * d_tdivzstepv; - - d_zistepu = p_normal[0] * xscaleinv * distinv; - d_zistepv = -p_normal[1] * yscaleinv * distinv; - d_ziorigin = p_normal[2] * distinv - xcenter * d_zistepu - ycenter * d_zistepv; - - sadjust = (fixed16_t) ( ( DotProduct( r_polydesc.viewer_position, r_polydesc.vright) + r_polydesc.s_offset ) * 0x10000 ); - tadjust = (fixed16_t) ( ( DotProduct( r_polydesc.viewer_position, r_polydesc.vup ) + r_polydesc.t_offset ) * 0x10000 ); - -// -1 (-epsilon) so we never wander off the edge of the texture - bbextents = (r_polydesc.pixel_width << 16) - 1; - bbextentt = (r_polydesc.pixel_height << 16) - 1; -} - -/* -** R_DrawPoly -** -** Polygon drawing function. Uses the polygon described in r_polydesc -** to calculate edges and gradients, then renders the resultant spans. -** -** This should NOT be called externally since it doesn't do clipping! -*/ -static void R_DrawPoly( qboolean iswater ) -{ - int i, nump; - float ymin, ymax; - emitpoint_t *pverts; - espan_t spans[MAXHEIGHT+1]; - - s_polygon_spans = spans; - -// find the top and bottom vertices, and make sure there's at least one scan to -// draw - ymin = 999999.9; - ymax = -999999.9; - pverts = r_polydesc.pverts; - - for (i=0 ; iv < ymin) - { - ymin = pverts->v; - s_minindex = i; - } - - if (pverts->v > ymax) - { - ymax = pverts->v; - s_maxindex = i; - } - - pverts++; - } - - ymin = ceil (ymin); - ymax = ceil (ymax); - - if (ymin >= ymax) - return; // doesn't cross any scans at all - - cachewidth = r_polydesc.pixel_width; - cacheblock = r_polydesc.pixels; - -// copy the first vertex to the last vertex, so we don't have to deal with -// wrapping - nump = r_polydesc.nump; - pverts = r_polydesc.pverts; - pverts[nump] = pverts[0]; - - R_PolygonCalculateGradients (); - R_PolygonScanLeftEdge (); - R_PolygonScanRightEdge (); - - R_PolygonDrawSpans( s_polygon_spans, iswater ); -} - -/* -** R_DrawAlphaSurfaces -*/ -void R_DrawAlphaSurfaces( void ) -{ - - // is this used in HL? world does not seems to have transparent surfaces - // world water does not have alpha without special compilers - msurface_t *s = r_alpha_surfaces; - - RI.currentmodel = WORLDMODEL; - - modelorg[0] = -r_origin[0]; - modelorg[1] = -r_origin[1]; - modelorg[2] = -r_origin[2]; - - while ( s ) - { - R_BuildPolygonFromSurface( s ); - -// if (s->texinfo->flags & SURF_TRANS66) -// R_ClipAndDrawPoly( 0.60f, ( s->texinfo->flags & SURF_WARP) != 0, true ); -// else -// R_ClipAndDrawPoly( 0.30f, ( s->texinfo->flags & SURF_WARP) != 0, true ); - R_ClipAndDrawPoly( 1, false, true ); - - s = s->texturechain; // s->nextalphasurface; - } - - r_alpha_surfaces = NULL; -} - -/* -** R_IMFlatShadedQuad -*/ -void R_IMFlatShadedQuad( vec3_t a, vec3_t b, vec3_t c, vec3_t d, int color, float alpha ) -{ - vec3_t s0, s1; - - r_polydesc.nump = 4; - VectorCopy( r_origin, r_polydesc.viewer_position ); - - VectorCopy( a, r_clip_verts[0][0] ); - VectorCopy( b, r_clip_verts[0][1] ); - VectorCopy( c, r_clip_verts[0][2] ); - VectorCopy( d, r_clip_verts[0][3] ); - - r_clip_verts[0][0][3] = 0; - r_clip_verts[0][1][3] = 0; - r_clip_verts[0][2][3] = 0; - r_clip_verts[0][3][3] = 0; - - r_clip_verts[0][0][4] = 0; - r_clip_verts[0][1][4] = 0; - r_clip_verts[0][2][4] = 0; - r_clip_verts[0][3][4] = 0; - - VectorSubtract( d, c, s0 ); - VectorSubtract( c, b, s1 ); - CrossProduct( s0, s1, r_polydesc.vpn ); - VectorNormalize( r_polydesc.vpn ); - - r_polydesc.dist = DotProduct( r_polydesc.vpn, r_clip_verts[0][0] ); - - //r_polyblendcolor = color; - - R_ClipAndDrawPoly( alpha, false, false ); -} - From 8f5c72c510fc1a4b86b9262cc5a7ef5379550d83 Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 3 Apr 2019 23:24:10 +0700 Subject: [PATCH 060/115] ref_soft: Add macro to disable texture filter preventing slowdown on cvar checking --- r_main.c | 3 ++- r_scan.c | 23 +++++++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/r_main.c b/r_main.c index 3637b419..87fc4ed9 100644 --- a/r_main.c +++ b/r_main.c @@ -2064,8 +2064,9 @@ qboolean R_Init() sw_notransbrushes = gEngfuncs.Cvar_Get( "sw_notransbrushes", "0", FCVAR_ARCHIVE, "do not apply transparency to water/glasses (faster)"); sw_noalphabrushes = gEngfuncs.Cvar_Get( "sw_noalphabrushes", "0", FCVAR_ARCHIVE, "do not draw brush holes (faster)"); r_traceglow = gEngfuncs.Cvar_Get( "r_traceglow", "1", FCVAR_ARCHIVE, "cull flares behind models" ); - +#ifndef DISABLE_TEXFILTER sw_texfilt = gEngfuncs.Cvar_Get ("sw_texfilt", "0", 0, "texture dither"); +#endif //r_lefthand = ri.Cvar_Get( "hand", "0", FCVAR_USERINFO | FCVAR_ARCHIVE ); // r_speeds = ri.Cvar_Get ("r_speeds", "0", 0); r_decals = gEngfuncs.pfnGetCvarPointer( "r_decals", 0 ); diff --git a/r_scan.c b/r_scan.c index 77d151ed..fa5855c3 100644 --- a/r_scan.c +++ b/r_scan.c @@ -564,7 +564,6 @@ void NonTurbulent8 (espan_t *pspan) #if !id386 - int kernel[2][2][2] = { { @@ -577,7 +576,11 @@ int kernel[2][2][2] = {0,16384} } }; - +#ifndef DISABLE_TEXFILTER +#define SW_TEXFILT (sw_texfilt->value == 1.0f) +#else +#define SW_TEXFILT 0 +#endif /* ============= D_DrawSpans16 @@ -700,7 +703,7 @@ void D_DrawSpans16 (espan_t *pspan) // Drawing phrase - if (sw_texfilt->value == 0.0f) + if (!SW_TEXFILT) { do { @@ -709,7 +712,7 @@ void D_DrawSpans16 (espan_t *pspan) t += tstep; } while (--spancount > 0); } - else if (sw_texfilt->value == 1.0f) + else { do { @@ -871,7 +874,7 @@ void D_AlphaSpans16 (espan_t *pspan) // Drawing phrase - if (sw_texfilt->value == 0.0f) + if (!SW_TEXFILT) { do { @@ -893,7 +896,7 @@ void D_AlphaSpans16 (espan_t *pspan) t += tstep; } while (--spancount > 0); } - else if (sw_texfilt->value == 1.0f) + else { do { @@ -1067,7 +1070,7 @@ void D_BlendSpans16 (espan_t *pspan, int alpha) // Drawing phrase - if (sw_texfilt->value == 0.0f) + if (!SW_TEXFILT) { do { @@ -1089,7 +1092,7 @@ void D_BlendSpans16 (espan_t *pspan, int alpha) t += tstep; } while (--spancount > 0); } - else if (sw_texfilt->value == 1.0f) + else { do { @@ -1263,7 +1266,7 @@ void D_AddSpans16 (espan_t *pspan) // Drawing phrase - if (sw_texfilt->value == 0.0f) + if (!SW_TEXFILT) { do { @@ -1284,7 +1287,7 @@ void D_AddSpans16 (espan_t *pspan) t += tstep; } while (--spancount > 0); } - else if (sw_texfilt->value == 1.0f) + else { do { From b5e1382232dbb25f21fcef477eff355e3818e2ae Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 4 Apr 2019 00:12:57 +0700 Subject: [PATCH 061/115] ref_soft: Merge some globals --- r_bsp.c | 43 ++++++++++++------------ r_decals.c | 2 +- r_edge.c | 25 +++++++------- r_light.c | 4 +-- r_local.h | 38 +++++++-------------- r_main.c | 66 +++++++++++++++---------------------- r_misc.c | 93 ++++++++++++++++++++++++++-------------------------- r_polyse.c | 2 ++ r_rast.c | 29 ++++++++-------- r_surf.c | 10 +++--- r_trialias.c | 24 +++++++------- 11 files changed, 153 insertions(+), 183 deletions(-) diff --git a/r_bsp.c b/r_bsp.c index 3fcbb62d..a9640f22 100644 --- a/r_bsp.c +++ b/r_bsp.c @@ -25,7 +25,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // current entity info // qboolean insubmodel; -vec3_t modelorg; // modelorg is the viewpoint reletive to // the currently rendering entity vec3_t r_entorigin; // the currently rendering entity in world // coordinates @@ -165,10 +164,10 @@ void R_RotateBmodel (void) // // rotate modelorg and the transformation matrix // - R_EntityRotate (modelorg); - R_EntityRotate (vpn); - R_EntityRotate (vright); - R_EntityRotate (vup); + R_EntityRotate (tr.modelorg); + R_EntityRotate (RI.vforward); + R_EntityRotate (RI.vright); + R_EntityRotate (RI.vup); R_TransformFrustum (); } @@ -495,7 +494,7 @@ void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) pn = pnode->children[i]; // we're done with this branch if the node or leaf isn't in the PVS - if (pn->visframe == r_visframecount) + if (pn->visframe == tr.visframecount) { if (pn->contents < 0) { @@ -667,7 +666,7 @@ void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel, mnode_t *topnode) // find which side of the node we are on pplane = psurf->plane; - dot = DotProduct (modelorg, pplane->normal) - pplane->dist; + dot = DotProduct (tr.modelorg, pplane->normal) - pplane->dist; // draw the polygon if (( !(psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || @@ -742,7 +741,7 @@ void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags, mnode_t *topnode) // find which side of the node we are on pplane = psurf->plane; - dot = DotProduct (modelorg, pplane->normal) - pplane->dist; + dot = DotProduct (tr.modelorg, pplane->normal) - pplane->dist; // draw the polygon if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) || @@ -779,7 +778,7 @@ void R_RecursiveWorldNode (mnode_t *node, int clipflags) if (node->contents == CONTENTS_SOLID) return; // solid - if (node->visframe != r_visframecount) + if (node->visframe != tr.visframecount) return; // cull the clipping planes if not trivial accept @@ -796,14 +795,14 @@ void R_RecursiveWorldNode (mnode_t *node, int clipflags) // FIXME: do with fast look-ups or integer tests based on the sign bit // of the floating point values - pindex = pfrustum_indexes[i]; + pindex = qfrustum.pfrustum_indexes[i]; rejectpt[0] = (float)node->minmaxs[pindex[0]]; rejectpt[1] = (float)node->minmaxs[pindex[1]]; rejectpt[2] = (float)node->minmaxs[pindex[2]]; - d = DotProduct (rejectpt, view_clipplanes[i].normal); - d -= view_clipplanes[i].dist; + d = DotProduct (rejectpt, qfrustum.view_clipplanes[i].normal); + d -= qfrustum.view_clipplanes[i].dist; if (d <= 0) return; @@ -812,8 +811,8 @@ void R_RecursiveWorldNode (mnode_t *node, int clipflags) acceptpt[1] = (float)node->minmaxs[pindex[3+1]]; acceptpt[2] = (float)node->minmaxs[pindex[3+2]]; - d = DotProduct (acceptpt, view_clipplanes[i].normal); - d -= view_clipplanes[i].dist; + d = DotProduct (acceptpt, qfrustum.view_clipplanes[i].normal); + d -= qfrustum.view_clipplanes[i].dist; if (d >= 0) clipflags &= ~(1<visframe = r_framecount; + (*mark)->visframe = tr.framecount; mark++; } while (--c); } @@ -858,16 +857,16 @@ void R_RecursiveWorldNode (mnode_t *node, int clipflags) switch (plane->type) { case PLANE_X: - dot = modelorg[0] - plane->dist; + dot = tr.modelorg[0] - plane->dist; break; case PLANE_Y: - dot = modelorg[1] - plane->dist; + dot = tr.modelorg[1] - plane->dist; break; case PLANE_Z: - dot = modelorg[2] - plane->dist; + dot = tr.modelorg[2] - plane->dist; break; default: - dot = DotProduct (modelorg, plane->normal) - plane->dist; + dot = DotProduct (tr.modelorg, plane->normal) - plane->dist; break; } @@ -891,7 +890,7 @@ void R_RecursiveWorldNode (mnode_t *node, int clipflags) do { if ((surf->flags & SURF_PLANEBACK) && - (surf->visframe == r_framecount)) + (surf->visframe == tr.framecount)) { R_RenderFace (surf, clipflags); } @@ -904,7 +903,7 @@ void R_RecursiveWorldNode (mnode_t *node, int clipflags) do { if (!(surf->flags & SURF_PLANEBACK) && - (surf->visframe == r_framecount)) + (surf->visframe == tr.framecount)) { R_RenderFace (surf, clipflags); } @@ -941,7 +940,7 @@ void R_RenderWorld (void) RI.currententity = gEngfuncs.GetEntityByIndex(0); //RI.currententity->frame = (int)(gpGlobals->time*2); - VectorCopy (r_origin, modelorg); + VectorCopy (RI.vieworg, tr.modelorg); RI.currentmodel = WORLDMODEL; r_pcurrentvertbase = RI.currentmodel->vertexes; diff --git a/r_decals.c b/r_decals.c index 9bca9e18..8aba9c42 100644 --- a/r_decals.c +++ b/r_decals.c @@ -566,7 +566,7 @@ static void R_AddDecalToSurface( decal_t *pdecal, msurface_t *surf, decalinfo_t } // force surface cache rebuild - surf->dlightframe = r_framecount + 1; + surf->dlightframe = tr.framecount + 1; // tag surface pdecal->psurface = surf; diff --git a/r_edge.c b/r_edge.c index eec6f19f..4da740af 100644 --- a/r_edge.c +++ b/r_edge.c @@ -78,7 +78,6 @@ static float fv; static int miplevel; float scale_for_mip; -int ubasestep, errorterm, erroradjustup, erroradjustdown; // FIXME: should go away extern void R_RotateBmodel (void); @@ -944,9 +943,9 @@ void D_TurbulentSurf (surf_t *s) RI.currententity = NULL; // &r_worldentity; VectorCopy (world_transformed_modelorg, transformed_modelorg); - VectorCopy (base_vpn, vpn); - VectorCopy (base_vup, vup); - VectorCopy (base_vright, vright); + VectorCopy (RI.base_vpn, RI.vforward); + VectorCopy (RI.base_vup, RI.vup); + VectorCopy (RI.base_vright, RI.vright); R_TransformFrustum (); } } @@ -1081,9 +1080,9 @@ void D_AlphaSurf (surf_t *s) VectorCopy (world_transformed_modelorg, transformed_modelorg); - VectorCopy (base_vpn, vpn); - VectorCopy (base_vup, vup); - VectorCopy (base_vright, vright); + VectorCopy (RI.base_vpn, RI.vforward); + VectorCopy (RI.base_vup, RI.vup); + VectorCopy (RI.base_vright, RI.vright); R_TransformFrustum (); } @@ -1184,9 +1183,9 @@ void D_SolidSurf (surf_t *s) // VectorCopy (world_transformed_modelorg, transformed_modelorg); - VectorCopy (base_vpn, vpn); - VectorCopy (base_vup, vup); - VectorCopy (base_vright, vright); + VectorCopy (RI.base_vpn, RI.vforward); + VectorCopy (RI.base_vup, RI.vup); + VectorCopy (RI.base_vright, RI.vright); R_TransformFrustum (); RI.currententity = NULL; //&r_worldentity; } @@ -1232,8 +1231,8 @@ void D_DrawSurfaces (void) surf_t *s; // currententity = NULL; //&r_worldentity; - VectorSubtract (RI.vieworg, vec3_origin, modelorg); - TransformVector (modelorg, transformed_modelorg); + VectorSubtract (RI.vieworg, vec3_origin, tr.modelorg); + TransformVector (tr.modelorg, transformed_modelorg); VectorCopy (transformed_modelorg, world_transformed_modelorg); if (!sw_drawflat->value) @@ -1269,7 +1268,7 @@ void D_DrawSurfaces (void) D_DrawflatSurfaces (); //RI.currententity = NULL; //&r_worldentity; - VectorSubtract (RI.vieworg, vec3_origin, modelorg); + VectorSubtract (RI.vieworg, vec3_origin, tr.modelorg); R_TransformFrustum (); } diff --git a/r_light.c b/r_light.c index 010e594b..0e4c2077 100644 --- a/r_light.c +++ b/r_light.c @@ -131,10 +131,10 @@ void R_MarkLights( dlight_t *light, int bit, mnode_t *node ) if( !BoundsAndSphereIntersect( surf->info->mins, surf->info->maxs, light->origin, light->radius )) continue; // no intersection - if( surf->dlightframe != r_framecount )//tr.dlightframecount ) + if( surf->dlightframe != tr.framecount )//tr.dlightframecount ) { surf->dlightbits = 0; - surf->dlightframe = r_framecount; //tr.dlightframecount; + surf->dlightframe = tr.framecount; //tr.dlightframecount; } surf->dlightbits |= bit; } diff --git a/r_local.h b/r_local.h index d3a6610d..6b186e88 100644 --- a/r_local.h +++ b/r_local.h @@ -186,6 +186,11 @@ typedef struct vec3_t vright; vec3_t vup; + + vec3_t base_vup; + vec3_t base_vpn; + vec3_t base_vright; + vec3_t cullorigin; vec3_t cull_vforward; vec3_t cull_vright; @@ -232,13 +237,8 @@ typedef struct float fvrectright_adj, fvrectbottom_adj; // right and bottom edges, for clamping float fvrectright; // rightmost edge, for Alias clamping - float fvrectbottom; // bottommost edge, for Alias clamping - float horizontalFieldOfView; // at Z = 1.0, this many X is visible - // 2.0 = 90 degrees - float xOrigin; // should probably always be 0.5 - float yOrigin; // between be around 0.3 to 0.5 + float fvrectbottom; // bottommost edge, for Alias clampin - int ambientlight; } ref_instance_t; @@ -1067,8 +1067,6 @@ VARS ==================================================== */ -//extern int d_spanpixcount; -extern int r_framecount; // sequence # of current frame since Quake // started extern float r_aliasuvscale; // scale-up factor for screen u and v // on Alias vertices passed to driver @@ -1143,10 +1141,6 @@ extern int sintable[1280]; extern int intsintable[1280]; extern int blanktable[1280]; // PGM -extern vec3_t vup, base_vup; -extern vec3_t vpn, base_vpn; -extern vec3_t vright, base_vright; - extern surf_t *surfaces, *surface_p, *surf_max; // surfaces are generated in back to front order by the bsp, so if a surf @@ -1178,15 +1172,11 @@ extern edge_t edge_head; extern edge_t edge_tail; extern edge_t edge_aftertail; - -extern int r_frustum_indexes[4*6]; extern qboolean r_surfsonstack; -extern mleaf_t *r_viewleaf; extern int r_viewcluster, r_oldviewcluster; extern int r_clipflags; -extern int r_dlightframecount; //extern qboolean r_fov_greater_than_90; @@ -1215,19 +1205,16 @@ extern cvar_t *tracerblue; extern cvar_t *traceralpha; - -extern vec3_t modelorg; -extern vec3_t r_origin; -extern mplane_t screenedge[4]; - - -extern clipplane_t view_clipplanes[4]; -extern int *pfrustum_indexes[4]; +extern struct qfrustum_s { + mplane_t screenedge[4]; + clipplane_t view_clipplanes[4]; + int frustum_indexes[4*6]; + int *pfrustum_indexes[4]; +} qfrustum; extern cvar_t *r_fullbright; #define CACHESPOT(surf) ((surfcache_t**)surf->info->reserved) -extern int r_visframecount; extern int r_currentkey; extern int r_currentbkey; extern qboolean insubmodel; @@ -1237,7 +1224,6 @@ extern vec3_t r_entorigin; extern int r_leafkeys[MAX_MAP_LEAFS]; #define LEAF_KEY(pleaf) r_leafkeys[(pleaf - WORLDMODEL->leafs)] -extern int ubasestep, errorterm, erroradjustup, erroradjustdown; extern mvertex_t *r_pcurrentvertbase; diff --git a/r_main.c b/r_main.c index 87fc4ed9..c7d2ee6c 100644 --- a/r_main.c +++ b/r_main.c @@ -30,10 +30,6 @@ ref_instance_t RI; // view origin // -vec3_t vup, base_vup; -vec3_t vpn, base_vpn; -vec3_t vright, base_vright; -vec3_t r_origin; // // screen size info @@ -46,26 +42,18 @@ float aliasxscale, aliasyscale, aliasxcenter, aliasycenter; int r_screenwidth; -float verticalFieldOfView; -float xOrigin, yOrigin; -mplane_t screenedge[4]; // // refresh flags // -int r_framecount = 1; // so frame counts initialized to 0 don't match -int r_visframecount; + //int d_spanpixcount; //int r_polycount; //int r_drawnpolycount; //int r_wholepolycount; -int *pfrustum_indexes[4]; -int r_frustum_indexes[4*6]; - -mleaf_t *r_viewleaf; int r_viewcluster, r_oldviewcluster; cvar_t *r_lefthand; @@ -1152,14 +1140,14 @@ int R_BmodelCheckBBox (float *minmaxs) // FIXME: do with fast look-ups or integer tests based on the sign bit // of the floating point values - pindex = pfrustum_indexes[i]; + pindex = qfrustum.pfrustum_indexes[i]; rejectpt[0] = minmaxs[pindex[0]]; rejectpt[1] = minmaxs[pindex[1]]; rejectpt[2] = minmaxs[pindex[2]]; - d = DotProduct (rejectpt, view_clipplanes[i].normal); - d -= view_clipplanes[i].dist; + d = DotProduct (rejectpt, qfrustum.view_clipplanes[i].normal); + d -= qfrustum.view_clipplanes[i].dist; if (d <= 0) return BMODEL_FULLY_CLIPPED; @@ -1168,8 +1156,8 @@ int R_BmodelCheckBBox (float *minmaxs) acceptpt[1] = minmaxs[pindex[3+1]]; acceptpt[2] = minmaxs[pindex[3+2]]; - d = DotProduct (acceptpt, view_clipplanes[i].normal); - d -= view_clipplanes[i].dist; + d = DotProduct (acceptpt, qfrustum.view_clipplanes[i].normal); + d -= qfrustum.view_clipplanes[i].dist; if (d <= 0) clipflags |= (1<visframe != r_visframecount) + if (node->visframe != tr.visframecount) return NULL; // not visible at all if (node->contents < 0) @@ -1293,7 +1281,7 @@ void R_DrawBEntitiesOnList (void) float minmaxs[6]; mnode_t *topnode; - VectorCopy (modelorg, oldorigin); + VectorCopy (tr.modelorg, oldorigin); insubmodel = true; //r_dlightframecount = r_framecount; @@ -1335,7 +1323,7 @@ void R_DrawBEntitiesOnList (void) continue; // no part in a visible leaf VectorCopy (RI.currententity->origin, r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); + VectorSubtract (RI.vieworg, r_entorigin, tr.modelorg); //VectorSubtract (r_origin, RI.currententity->origin, modelorg); r_pcurrentvertbase = RI.currentmodel->vertexes; @@ -1394,10 +1382,10 @@ void R_DrawBEntitiesOnList (void) // put back world rotation and frustum clipping // FIXME: R_RotateBmodel should just work off base_vxx - VectorCopy (base_vpn, vpn); - VectorCopy (base_vup, vup); - VectorCopy (base_vright, vright); - VectorCopy (oldorigin, modelorg); + VectorCopy (RI.base_vpn, RI.vforward); + VectorCopy (RI.base_vup, RI.vup); + VectorCopy (RI.base_vright, RI.vright); + VectorCopy (oldorigin, tr.modelorg); R_TransformFrustum (); } @@ -1451,7 +1439,7 @@ void R_DrawBrushModel(cl_entity_t *pent) R_BeginEdgeFrame(); - VectorCopy (modelorg, oldorigin); + VectorCopy (tr.modelorg, oldorigin); insubmodel = true; //r_dlightframecount = r_framecount; @@ -1489,7 +1477,7 @@ void R_DrawBrushModel(cl_entity_t *pent) alphaspans = true; VectorCopy (RI.currententity->origin, r_entorigin); - VectorSubtract (r_origin, r_entorigin, modelorg); + VectorSubtract (RI.vieworg, r_entorigin, tr.modelorg); //VectorSubtract (r_origin, RI.currententity->origin, modelorg); r_pcurrentvertbase = RI.currentmodel->vertexes; @@ -1548,10 +1536,10 @@ void R_DrawBrushModel(cl_entity_t *pent) // put back world rotation and frustum clipping // FIXME: R_RotateBmodel should just work off base_vxx - VectorCopy (base_vpn, vpn); - VectorCopy (base_vup, vup); - VectorCopy (base_vright, vright); - VectorCopy (oldorigin, modelorg); + VectorCopy (RI.base_vpn, RI.vforward); + VectorCopy (RI.base_vup, RI.vup); + VectorCopy (RI.base_vright, RI.vright); + VectorCopy (oldorigin, tr.modelorg); R_TransformFrustum (); @@ -1704,7 +1692,7 @@ void R_MarkLeaves (void) if (r_oldviewcluster == r_viewcluster && !r_novis->value && r_viewcluster != -1) return; - r_visframecount++; + tr.visframecount++; r_oldviewcluster = r_viewcluster; gEngfuncs.R_FatPVS( RI.pvsorigin, REFPVS_RADIUS, RI.visbytes, FBitSet( RI.params, RP_OLDVIEWLEAF ), false ); @@ -1717,9 +1705,9 @@ void R_MarkLeaves (void) node = (mnode_t *) &WORLDMODEL->leafs[i+1]; do { - if (node->visframe == r_visframecount) + if (node->visframe == tr.visframecount) break; - node->visframe = r_visframecount; + node->visframe = tr.visframecount; node = node->parent; } while (node); } @@ -2098,12 +2086,10 @@ qboolean R_Init() // init draw stack tr.draw_list = &tr.draw_stack[0]; tr.draw_stack_pos = 0; - RI.yOrigin = YCENTERING; - RI.xOrigin = XCENTERING; - view_clipplanes[0].leftedge = true; - view_clipplanes[1].rightedge = true; - view_clipplanes[1].leftedge = view_clipplanes[2].leftedge =view_clipplanes[3].leftedge = false; - view_clipplanes[0].rightedge = view_clipplanes[2].rightedge = view_clipplanes[3].rightedge = false; + qfrustum.view_clipplanes[0].leftedge = true; + qfrustum.view_clipplanes[1].rightedge = true; + qfrustum.view_clipplanes[1].leftedge = qfrustum.view_clipplanes[2].leftedge =qfrustum.view_clipplanes[3].leftedge = false; + qfrustum.view_clipplanes[0].rightedge = qfrustum.view_clipplanes[2].rightedge = qfrustum.view_clipplanes[3].rightedge = false; R_StudioInit(); R_SpriteInit(); R_InitTurb(); diff --git a/r_misc.c b/r_misc.c index 27f7f857..7e26dd29 100644 --- a/r_misc.c +++ b/r_misc.c @@ -40,7 +40,7 @@ static float basemip[NUM_MIPS-1] = {1.0, 0.5*0.8, 0.25*0.8}; int d_scantable[MAXHEIGHT]; short *zspantable[MAXHEIGHT]; - +struct qfrustum_s qfrustum; /* ================ D_Patch @@ -132,17 +132,17 @@ void R_TransformFrustum (void) for (i=0 ; i<4 ; i++) { - v[0] = screenedge[i].normal[2]; - v[1] = -screenedge[i].normal[0]; - v[2] = screenedge[i].normal[1]; + v[0] = qfrustum.screenedge[i].normal[2]; + v[1] = -qfrustum.screenedge[i].normal[0]; + v[2] = qfrustum.screenedge[i].normal[1]; - v2[0] = v[1]*vright[0] + v[2]*vup[0] + v[0]*vpn[0]; - v2[1] = v[1]*vright[1] + v[2]*vup[1] + v[0]*vpn[1]; - v2[2] = v[1]*vright[2] + v[2]*vup[2] + v[0]*vpn[2]; + v2[0] = v[1]*RI.vright[0] + v[2]*RI.vup[0] + v[0]*RI.vforward[0]; + v2[1] = v[1]*RI.vright[1] + v[2]*RI.vup[1] + v[0]*RI.vforward[1]; + v2[2] = v[1]*RI.vright[2] + v[2]*RI.vup[2] + v[0]*RI.vforward[2]; - VectorCopy (v2, view_clipplanes[i].normal); + VectorCopy (v2, qfrustum.view_clipplanes[i].normal); - view_clipplanes[i].dist = DotProduct (modelorg, v2); + qfrustum.view_clipplanes[i].dist = DotProduct (tr.modelorg, v2); } } @@ -154,9 +154,9 @@ TransformVector */ void TransformVector (vec3_t in, vec3_t out) { - out[0] = DotProduct(in,vright); - out[1] = DotProduct(in,vup); - out[2] = DotProduct(in,vpn); + out[0] = DotProduct(in,RI.vright); + out[1] = DotProduct(in,RI.vup); + out[2] = DotProduct(in,RI.vforward); } /* @@ -184,13 +184,13 @@ void R_SetUpFrustumIndexes (void) { int i, j, *pindex; - pindex = r_frustum_indexes; + pindex = qfrustum.frustum_indexes; for (i=0 ; i<4 ; i++) { for (j=0 ; j<3 ; j++) { - if (view_clipplanes[i].normal[j] < 0) + if (qfrustum.view_clipplanes[i].normal[j] < 0) { pindex[j] = j; pindex[j+3] = j+3; @@ -203,7 +203,7 @@ void R_SetUpFrustumIndexes (void) } // FIXME: do just once at start - pfrustum_indexes[i] = pindex; + qfrustum.pfrustum_indexes[i] = pindex; pindex += 6; } } @@ -219,11 +219,11 @@ Guaranteed to be called before the first refresh void R_ViewChanged (vrect_t *vr) { int i; - float verticalFieldOfView, xOrigin, yOrigin; + float verticalFieldOfView, horizontalFieldOfView, xOrigin, yOrigin; RI.vrect = *vr; - RI.horizontalFieldOfView = 2*tan((float)RI.fov_x/360*M_PI); + horizontalFieldOfView = 2*tan((float)RI.fov_x/360*M_PI); verticalFieldOfView = 2*tan((float)RI.fov_y/360*M_PI); RI.fvrectx = (float)RI.vrect.x; @@ -249,8 +249,8 @@ void R_ViewChanged (vrect_t *vr) RI.aliasvrectbottom = RI.aliasvrect.y + RI.aliasvrect.height; - xOrigin = RI.xOrigin;// = r_origin[0]; - yOrigin = RI.yOrigin;// = r_origin[1]; + xOrigin = XCENTERING; + yOrigin = YCENTERING; #define PLANE_ANYZ 5 // values for perspective projection // if math were exact, the values would range from 0.5 to to range+0.5 @@ -265,7 +265,7 @@ void R_ViewChanged (vrect_t *vr) RI.vrect.y - 0.5; aliasycenter = ycenter * r_aliasuvscale; - xscale = RI.vrect.width / RI.horizontalFieldOfView; + xscale = RI.vrect.width / horizontalFieldOfView; aliasxscale = xscale * r_aliasuvscale; xscaleinv = 1.0 / xscale; @@ -276,32 +276,32 @@ void R_ViewChanged (vrect_t *vr) //yscaleshrink = xscaleshrink; // left side clip - screenedge[0].normal[0] = -1.0 / (xOrigin*RI.horizontalFieldOfView); - screenedge[0].normal[1] = 0; - screenedge[0].normal[2] = 1; - screenedge[0].type = PLANE_ANYZ; + qfrustum.screenedge[0].normal[0] = -1.0 / (xOrigin*horizontalFieldOfView); + qfrustum.screenedge[0].normal[1] = 0; + qfrustum.screenedge[0].normal[2] = 1; + qfrustum.screenedge[0].type = PLANE_ANYZ; // right side clip - screenedge[1].normal[0] = - 1.0 / ((1.0-xOrigin)*RI.horizontalFieldOfView); - screenedge[1].normal[1] = 0; - screenedge[1].normal[2] = 1; - screenedge[1].type = PLANE_ANYZ; + qfrustum.screenedge[1].normal[0] = + 1.0 / ((1.0-xOrigin)*horizontalFieldOfView); + qfrustum.screenedge[1].normal[1] = 0; + qfrustum.screenedge[1].normal[2] = 1; + qfrustum.screenedge[1].type = PLANE_ANYZ; // top side clip - screenedge[2].normal[0] = 0; - screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView); - screenedge[2].normal[2] = 1; - screenedge[2].type = PLANE_ANYZ; + qfrustum.screenedge[2].normal[0] = 0; + qfrustum.screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView); + qfrustum.screenedge[2].normal[2] = 1; + qfrustum.screenedge[2].type = PLANE_ANYZ; // bottom side clip - screenedge[3].normal[0] = 0; - screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView); - screenedge[3].normal[2] = 1; - screenedge[3].type = PLANE_ANYZ; + qfrustum.screenedge[3].normal[0] = 0; + qfrustum.screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView); + qfrustum.screenedge[3].normal[2] = 1; + qfrustum.screenedge[3].type = PLANE_ANYZ; for (i=0 ; i<4 ; i++) - VectorNormalize (screenedge[i].normal); + VectorNormalize (qfrustum.screenedge[i].normal); D_ViewChanged (); } @@ -323,20 +323,19 @@ void R_SetupFrameQ (void) D_FlushCaches( false ); // so all lighting changes } - r_framecount++; + //tr.framecount++; // build the transformation matrix for the given view angles - VectorCopy (RI.vieworg, modelorg); - VectorCopy (RI.vieworg, r_origin); + VectorCopy (RI.vieworg, tr.modelorg); - AngleVectors (RI.viewangles, vpn, vright, vup); + //AngleVectors (RI.viewangles, RI.vforward, RI.vright, RI.vup); // current viewleaf if ( RI.drawWorld ) { - r_viewleaf = gEngfuncs.Mod_PointInLeaf (r_origin, WORLDMODEL->nodes); - r_viewcluster = r_viewleaf->cluster; + RI.viewleaf = gEngfuncs.Mod_PointInLeaf (RI.vieworg, WORLDMODEL->nodes); + r_viewcluster = RI.viewleaf->cluster; } // if (sw_waterwarp->value && (r_newrefdef.rdflags & RDF_UNDERWATER) ) @@ -372,9 +371,9 @@ void R_SetupFrameQ (void) R_SetUpFrustumIndexes (); // save base values - VectorCopy (vpn, base_vpn); - VectorCopy (vright, base_vright); - VectorCopy (vup, base_vup); + VectorCopy (RI.vforward, RI.base_vpn); + VectorCopy (RI.vright, RI.base_vright); + VectorCopy (RI.vup, RI.base_vup); // clear frame counts /* c_faceclip = 0; diff --git a/r_polyse.c b/r_polyse.c index abededfa..cd23a7f0 100644 --- a/r_polyse.c +++ b/r_polyse.c @@ -90,6 +90,8 @@ int d_sfracbasestep, d_tfracbasestep; int d_ziextrastep, d_zibasestep; int d_pzextrastep, d_pzbasestep; +static int ubasestep, errorterm, erroradjustup, erroradjustdown; + typedef struct { int quotient; int remainder; diff --git a/r_rast.c b/r_rast.c index fb326714..ba6aed4b 100644 --- a/r_rast.c +++ b/r_rast.c @@ -35,7 +35,6 @@ int c_faceclip; // number of faces clipped clipplane_t *entity_clipplanes; -clipplane_t view_clipplanes[4]; clipplane_t world_clipplanes[16]; medge_t *r_pedge; @@ -239,7 +238,7 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) world = &pv0->position[0]; // transform and project - VectorSubtract (world, modelorg, local); + VectorSubtract (world, tr.modelorg, local); TransformVector (local, transformed); if (transformed[2] < NEAR_CLIP) @@ -268,7 +267,7 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) world = &pv1->position[0]; // transform and project - VectorSubtract (world, modelorg, local); + VectorSubtract (world, tr.modelorg, local); TransformVector (local, transformed); if (transformed[2] < NEAR_CLIP) @@ -312,7 +311,7 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) if (cacheoffset != 0x7FFFFFFF) { cacheoffset = FULLY_CLIPPED_CACHED | - (r_framecount & FRAMECOUNT_MASK); + (tr.framecount & FRAMECOUNT_MASK); } return; // horizontal edge @@ -471,7 +470,7 @@ void R_ClipEdge (mvertex_t *pv0, mvertex_t *pv1, clipplane_t *clip) // we do cache fully clipped edges if (!r_leftclipped) cacheoffset = FULLY_CLIPPED_CACHED | - (r_framecount & FRAMECOUNT_MASK); + (tr.framecount & FRAMECOUNT_MASK); return; } @@ -590,8 +589,8 @@ void R_RenderFace (msurface_t *fa, int clipflags) { if (clipflags & mask) { - view_clipplanes[i].next = pclip; - pclip = &view_clipplanes[i]; + qfrustum.view_clipplanes[i].next = pclip; + pclip = &qfrustum.view_clipplanes[i]; } } @@ -617,7 +616,7 @@ void R_RenderFace (msurface_t *fa, int clipflags) if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) { if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) == - r_framecount) + tr.framecount) { r_lastvertvalid = false; continue; @@ -661,7 +660,7 @@ void R_RenderFace (msurface_t *fa, int clipflags) if (r_pedge->cachededgeoffset & FULLY_CLIPPED_CACHED) { if ((r_pedge->cachededgeoffset & FRAMECOUNT_MASK) == - r_framecount) + tr.framecount) { r_lastvertvalid = false; continue; @@ -715,7 +714,7 @@ void R_RenderFace (msurface_t *fa, int clipflags) r_pedge = &tedge; r_lastvertvalid = false; r_nearzionly = true; - R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next); + R_ClipEdge (&r_rightexit, &r_rightenter, qfrustum.view_clipplanes[1].next); } // if no edges made it out, return without posting the surface @@ -737,7 +736,7 @@ void R_RenderFace (msurface_t *fa, int clipflags) // FIXME: cache this? TransformVector (pplane->normal, p_normal); // FIXME: cache this? - distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal)); + distinv = 1.0 / (pplane->dist - DotProduct (tr.modelorg, pplane->normal)); surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; @@ -797,8 +796,8 @@ void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf) { if (r_clipflags & mask) { - view_clipplanes[i].next = pclip; - pclip = &view_clipplanes[i]; + qfrustum.view_clipplanes[i].next = pclip; + pclip = &qfrustum.view_clipplanes[i]; } } @@ -836,7 +835,7 @@ void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf) { r_pedge = &tedge; r_nearzionly = true; - R_ClipEdge (&r_rightexit, &r_rightenter, view_clipplanes[1].next); + R_ClipEdge (&r_rightexit, &r_rightenter, qfrustum.view_clipplanes[1].next); } // if no edges made it out, return without posting the surface @@ -858,7 +857,7 @@ void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf) // FIXME: cache this? TransformVector (pplane->normal, p_normal); // FIXME: cache this? - distinv = 1.0 / (pplane->dist - DotProduct (modelorg, pplane->normal)); + distinv = 1.0 / (pplane->dist - DotProduct (tr.modelorg, pplane->normal)); surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; diff --git a/r_surf.c b/r_surf.c index 533d7acf..633657e4 100644 --- a/r_surf.c +++ b/r_surf.c @@ -217,7 +217,7 @@ static void R_BuildLightMap( ) } // add all the dynamic lights - if( surf->dlightframe == r_framecount ) + if( surf->dlightframe == tr.framecount ) R_AddDynamicLights( surf ); // Put into texture format @@ -1148,12 +1148,12 @@ surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) { if( tr.lightstylevalue[surface->styles[maps]] != surface->cached_light[maps] ) { - surface->dlightframe = r_framecount; + surface->dlightframe = tr.framecount; } } - if (cache && !cache->dlight && surface->dlightframe != r_framecount + if (cache && !cache->dlight && surface->dlightframe != tr.framecount && cache->image == r_drawsurf.image && cache->lightadj[0] == r_drawsurf.lightadj[0] && cache->lightadj[1] == r_drawsurf.lightadj[1] @@ -1161,7 +1161,7 @@ surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) && cache->lightadj[3] == r_drawsurf.lightadj[3] ) return cache; - if( surface->dlightframe == r_framecount ) + if( surface->dlightframe == tr.framecount ) { int i; // invalidate dlight cache @@ -1193,7 +1193,7 @@ surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) cache->mipscale = surfscale; } - if (surface->dlightframe == r_framecount) + if (surface->dlightframe == tr.framecount) cache->dlight = 1; else cache->dlight = 0; diff --git a/r_trialias.c b/r_trialias.c index 4c74c533..29fab753 100644 --- a/r_trialias.c +++ b/r_trialias.c @@ -96,9 +96,9 @@ void R_SetUpWorldTransform (void) aliasoldworldtransform[i][0] = aliasworldtransform[i][2] = s_alias_up[i]; } - aliasworldtransform[0][3] = -r_origin[0]; - aliasworldtransform[1][3] = -r_origin[1]; - aliasworldtransform[2][3] = -r_origin[2]; + aliasworldtransform[0][3] = -RI.vieworg[0]; + aliasworldtransform[1][3] = -RI.vieworg[1]; + aliasworldtransform[2][3] = -RI.vieworg[2]; //aliasoldworldtransform[0][3] = RI.currententity->oldorigin[0]-r_origin[0]; //aliasoldworldtransform[1][3] = RI.currententity->oldorigin[1]-r_origin[1]; @@ -110,11 +110,11 @@ void R_SetUpWorldTransform (void) // R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix); // TODO: should be global, set when vright, etc., set - VectorCopy (vright, viewmatrix[0]); - VectorCopy (vup, viewmatrix[1]); + VectorCopy (RI.vright, viewmatrix[0]); + VectorCopy (RI.vup, viewmatrix[1]); VectorInverse (viewmatrix[1]); //VectorScale(viewmatrix[1], -1, viewmatrix[1]); - VectorCopy (vpn, viewmatrix[2]); + VectorCopy (RI.vforward, viewmatrix[2]); viewmatrix[0][3] = 0; viewmatrix[1][3] = 0; @@ -169,9 +169,9 @@ void R_AliasSetUpTransform (void) aliasoldworldtransform[i][0] = aliasworldtransform[i][2] = s_alias_up[i]; } - aliasworldtransform[0][3] = RI.currententity->origin[0]-r_origin[0]; - aliasworldtransform[1][3] = RI.currententity->origin[1]-r_origin[1]; - aliasworldtransform[2][3] = RI.currententity->origin[2]-r_origin[2]; + aliasworldtransform[0][3] = RI.currententity->origin[0]-RI.vieworg[0]; + aliasworldtransform[1][3] = RI.currententity->origin[1]-RI.vieworg[1]; + aliasworldtransform[2][3] = RI.currententity->origin[2]-RI.vieworg[2]; //aliasoldworldtransform[0][3] = RI.currententity->oldorigin[0]-r_origin[0]; //aliasoldworldtransform[1][3] = RI.currententity->oldorigin[1]-r_origin[1]; @@ -183,11 +183,11 @@ void R_AliasSetUpTransform (void) // R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix); // TODO: should be global, set when vright, etc., set - VectorCopy (vright, viewmatrix[0]); - VectorCopy (vup, viewmatrix[1]); + VectorCopy (RI.vright, viewmatrix[0]); + VectorCopy (RI.vup, viewmatrix[1]); VectorInverse (viewmatrix[1]); //VectorScale(viewmatrix[1], -1, viewmatrix[1]); - VectorCopy (vpn, viewmatrix[2]); + VectorCopy (RI.vforward, viewmatrix[2]); viewmatrix[0][3] = 0; viewmatrix[1][3] = 0; From 8d88ecb951a0f485ee755a4936196b5e9d92804f Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 4 Apr 2019 00:29:35 +0700 Subject: [PATCH 062/115] ref_soft: Remove more unused globals/functions --- r_context.c | 2 +- r_local.h | 27 --------- r_main.c | 156 +--------------------------------------------------- r_misc.c | 26 ++------- r_triapi.c | 4 +- 5 files changed, 10 insertions(+), 205 deletions(-) diff --git a/r_context.c b/r_context.c index 5b279706..12257fde 100644 --- a/r_context.c +++ b/r_context.c @@ -185,7 +185,7 @@ static int GL_RenderGetParm( int parm, int arg ) Assert( arg >= 0 && arg < 6 ); return tr.skyboxTextures[arg]; case PARM_TEX_SKYTEXNUM: - return tr.skytexturenum; + return 0; case PARM_TEX_LIGHTMAP: arg = bound( 0, arg, MAX_LIGHTMAPS - 1 ); return tr.lightmapTextures[arg]; diff --git a/r_local.h b/r_local.h index 6b186e88..5f7cd8f9 100644 --- a/r_local.h +++ b/r_local.h @@ -185,8 +185,6 @@ typedef struct vec3_t vforward; vec3_t vright; vec3_t vup; - - vec3_t base_vup; vec3_t base_vpn; vec3_t base_vright; @@ -196,15 +194,6 @@ typedef struct vec3_t cull_vright; vec3_t cull_vup; - float farClip; - - qboolean fogCustom; - qboolean fogEnabled; - qboolean fogSkybox; - vec4_t fogColor; - float fogDensity; - float fogStart; - float fogEnd; int cached_contents; // in water int cached_waterlevel; // was in water @@ -220,7 +209,6 @@ typedef struct byte visbytes[(MAX_MAP_LEAFS+7)/8];// actual PVS for current frame float viewplanedist; - mplane_t clipPlane; // q2 oldrefdef vrect_t vrect; // subwindow in video for refresh @@ -268,9 +256,6 @@ typedef struct int skyboxTextures[6]; // skybox sides int cinTexture; // cinematic texture - int skytexturenum; // this not a gl_texturenum! - int skyboxbasenum; // start with 5800 - // entity lists draw_list_t draw_stack[MAX_DRAW_STACK]; int draw_stack_pos; @@ -1070,20 +1055,15 @@ VARS // started extern float r_aliasuvscale; // scale-up factor for screen u and v // on Alias vertices passed to driver -extern qboolean r_dowarp; extern affinetridesc_t r_affinetridesc; -extern vec3_t r_pright, r_pup, r_ppn; - void D_DrawSurfaces (void); void R_DrawParticle( void ); void D_ViewChanged (void); void D_WarpScreen (void); void R_PolysetUpdateTables (void); -extern void *acolormap; // FIXME: should go away - //=======================================================================// // callbacks to Quake @@ -1167,13 +1147,6 @@ extern edge_t *r_edges, *edge_p, *edge_max; extern edge_t *newedges[MAXHEIGHT]; extern edge_t *removeedges[MAXHEIGHT]; -// FIXME: make stack vars when debugging done -extern edge_t edge_head; -extern edge_t edge_tail; -extern edge_t edge_aftertail; - -extern qboolean r_surfsonstack; - extern int r_viewcluster, r_oldviewcluster; extern int r_clipflags; diff --git a/r_main.c b/r_main.c index c7d2ee6c..f2ce33bd 100644 --- a/r_main.c +++ b/r_main.c @@ -115,8 +115,6 @@ short *d_pzbuffer; unsigned int d_zrowbytes; unsigned int d_zwidth; -qboolean r_dowarp; - mvertex_t *r_pcurrentvertbase; //int c_surf; @@ -797,154 +795,6 @@ static image_t *R_RecursiveFindWaterTexture( const mnode_t *node, const mnode_t return NULL; } -/* -============= -R_CheckFog - -check for underwater fog -Using backward recursion to find waterline leaf -from underwater leaf (idea: XaeroX) -============= -*/ -static void R_CheckFog( void ) -{ - cl_entity_t *ent; - image_t *tex; - int i, cnt, count; - - // quake global fog - if( ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE )) - { - if( !MOVEVARS->fog_settings ) - { - // if( pglIsEnabled( GL_FOG )) - // pglDisable( GL_FOG ); - RI.fogEnabled = false; - return; - } - - // quake-style global fog - RI.fogColor[0] = ((MOVEVARS->fog_settings & 0xFF000000) >> 24) / 255.0f; - RI.fogColor[1] = ((MOVEVARS->fog_settings & 0xFF0000) >> 16) / 255.0f; - RI.fogColor[2] = ((MOVEVARS->fog_settings & 0xFF00) >> 8) / 255.0f; - RI.fogDensity = ((MOVEVARS->fog_settings & 0xFF) / 255.0f) * 0.01f; - RI.fogStart = RI.fogEnd = 0.0f; - RI.fogColor[3] = 1.0f; - RI.fogCustom = false; - RI.fogEnabled = true; - RI.fogSkybox = true; - return; - } - - RI.fogEnabled = false; - - if( RI.onlyClientDraw || ENGINE_GET_PARM( PARM_WATER_LEVEL ) < 3 || !RI.drawWorld || !RI.viewleaf ) - { - if( RI.cached_waterlevel == 3 ) - { - // in some cases waterlevel jumps from 3 to 1. Catch it - RI.cached_waterlevel = ENGINE_GET_PARM( PARM_WATER_LEVEL ); - RI.cached_contents = CONTENTS_EMPTY; - //if( !RI.fogCustom ) pglDisable( GL_FOG ); - } - return; - } - - ent = gEngfuncs.CL_GetWaterEntity( RI.vieworg ); - if( ent && ent->model && ent->model->type == mod_brush && ent->curstate.skin < 0 ) - cnt = ent->curstate.skin; - else cnt = RI.viewleaf->contents; - - RI.cached_waterlevel = ENGINE_GET_PARM( PARM_WATER_LEVEL ); - - if( !IsLiquidContents( RI.cached_contents ) && IsLiquidContents( cnt )) - { - tex = NULL; - - // check for water texture - if( ent && ent->model && ent->model->type == mod_brush ) - { - msurface_t *surf; - - count = ent->model->nummodelsurfaces; - - for( i = 0, surf = &ent->model->surfaces[ent->model->firstmodelsurface]; i < count; i++, surf++ ) - { - if( surf->flags & SURF_DRAWTURB && surf->texinfo && surf->texinfo->texture ) - { - tex = R_GetTexture( surf->texinfo->texture->gl_texturenum ); - RI.cached_contents = ent->curstate.skin; - break; - } - } - } - else - { - tex = R_RecursiveFindWaterTexture( RI.viewleaf->parent, NULL, false ); - if( tex ) RI.cached_contents = RI.viewleaf->contents; - } - - if( !tex ) return; // no valid fogs - - // copy fog params - RI.fogColor[0] = tex->fogParams[0] / 255.0f; - RI.fogColor[1] = tex->fogParams[1] / 255.0f; - RI.fogColor[2] = tex->fogParams[2] / 255.0f; - RI.fogDensity = tex->fogParams[3] * 0.000025f; - RI.fogStart = RI.fogEnd = 0.0f; - RI.fogColor[3] = 1.0f; - RI.fogCustom = false; - RI.fogEnabled = true; - RI.fogSkybox = true; - } - else - { - RI.fogCustom = false; - RI.fogEnabled = true; - RI.fogSkybox = true; - } -} - -/* -============= -R_CheckGLFog - -special condition for Spirit 1.9 -that used direct calls of glFog-functions -============= -*/ -static void R_CheckGLFog( void ) -{ -#ifdef HACKS_RELATED_HLMODS - if(( !RI.fogEnabled && !RI.fogCustom ) && pglIsEnabled( GL_FOG ) && VectorIsNull( RI.fogColor )) - { - // fill the fog color from GL-state machine - pglGetFloatv( GL_FOG_COLOR, RI.fogColor ); - RI.fogSkybox = true; - } -#endif -} - -/* -============= -R_DrawFog - -============= -*/ -void R_DrawFog( void ) -{ - if( !RI.fogEnabled ) return; -#if 0 - pglEnable( GL_FOG ); - if( gEngfuncs.Host_IsQuakeCompatible( )) - pglFogi( GL_FOG_MODE, GL_EXP2 ); - else pglFogi( GL_FOG_MODE, GL_EXP ); - pglFogf( GL_FOG_DENSITY, RI.fogDensity ); - pglFogfv( GL_FOG_COLOR, RI.fogColor ); - pglHint( GL_FOG_HINT, GL_NICEST ); -#endif -} - /* ============= R_DrawEntitiesOnList @@ -1744,15 +1594,12 @@ void R_RenderScene( void ) R_PushDlights(); // R_SetupGL( true ); - R_Clear( ~0 ); + //R_Clear( ~0 ); R_MarkLeaves(); - R_DrawFog (); // R_PushDlights (r_worldmodel); ?? - R_CheckGLFog(); //R_DrawWorld(); R_EdgeDrawing (); - R_CheckFog(); gEngfuncs.CL_ExtraUpdate (); // don't let sound get messed up if going slow @@ -1854,7 +1701,6 @@ void R_SetupRefParams( const ref_viewpass_t *rvp ) RI.params = RP_NONE; RI.drawWorld = FBitSet( rvp->flags, RF_DRAW_WORLD ); RI.onlyClientDraw = FBitSet( rvp->flags, RF_ONLY_CLIENTDRAW ); - RI.farClip = 0; if( !FBitSet( rvp->flags, RF_DRAW_CUBEMAP )) RI.drawOrtho = FBitSet( rvp->flags, RF_DRAW_OVERVIEW ); diff --git a/r_misc.c b/r_misc.c index 7e26dd29..e4e3f3fe 100644 --- a/r_misc.c +++ b/r_misc.c @@ -341,29 +341,15 @@ void R_SetupFrameQ (void) // if (sw_waterwarp->value && (r_newrefdef.rdflags & RDF_UNDERWATER) ) // r_dowarp = true; // else - r_dowarp = false; - if (r_dowarp) - { // warp into off screen buffer - vrect.x = 0; - vrect.y = 0; - //vrect.width = r_newrefdef.width < WARP_WIDTH ? r_newrefdef.width : WARP_WIDTH; - //vrect.height = r_newrefdef.height < WARP_HEIGHT ? r_newrefdef.height : WARP_HEIGHT; + vrect.x = 0;//r_newrefdef.x; + vrect.y = 0;//r_newrefdef.y; + vrect.width = gpGlobals->width; + vrect.height = gpGlobals->height; - d_viewbuffer = r_warpbuffer; - r_screenwidth = WARP_WIDTH; - } - else - { - vrect.x = 0;//r_newrefdef.x; - vrect.y = 0;//r_newrefdef.y; - vrect.width = gpGlobals->width; - vrect.height = gpGlobals->height; + d_viewbuffer = (void *)vid.buffer; + r_screenwidth = vid.rowbytes; - d_viewbuffer = (void *)vid.buffer; - r_screenwidth = vid.rowbytes; - } - R_ViewChanged (&vrect); // start off with just the four screen edge clip planes diff --git a/r_triapi.c b/r_triapi.c index 8402bca7..db971c94 100644 --- a/r_triapi.c +++ b/r_triapi.c @@ -455,8 +455,8 @@ TriForParams */ void TriFogParams( float flDensity, int iFogSkybox ) { - RI.fogDensity = flDensity; - RI.fogSkybox = iFogSkybox; + //RI.fogDensity = flDensity; + //RI.fogSkybox = iFogSkybox; } /* From 4bbcd5daef1bd5bc5a55e7a3caafea31f66ec127 Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 4 Apr 2019 01:32:06 +0700 Subject: [PATCH 063/115] ref_soft: Use r_math, this will fix beamfollow and glow sprites --- r_context.c | 4 - r_local.h | 5 +- r_main.c | 16 +++- r_math.c | 267 ++++++++++++++++++++++++++++++++++++++++++++++++++++ r_sprite.c | 1 + r_triapi.c | 7 +- 6 files changed, 285 insertions(+), 15 deletions(-) create mode 100644 r_math.c diff --git a/r_context.c b/r_context.c index 12257fde..b9e32f1d 100644 --- a/r_context.c +++ b/r_context.c @@ -447,10 +447,6 @@ byte *Mod_GetCurrentVis() return NULL; } -void R_ScreenToWorld(const vec3_t screen, vec3_t point) -{ - -} void GL_SetupAttributes( int safegl ) { gEngfuncs.Con_Reportf( "Creating an extended GL context for debug...\n" ); diff --git a/r_local.h b/r_local.h index 5f7cd8f9..7906dfc5 100644 --- a/r_local.h +++ b/r_local.h @@ -196,6 +196,7 @@ typedef struct int cached_contents; // in water int cached_waterlevel; // was in water + float farClip; float skyMins[2][6]; float skyMaxs[2][6]; @@ -474,7 +475,7 @@ void R_FindViewLeaf( void ); void R_PushScene( void ); void R_PopScene( void ); void R_DrawFog( void ); -#if 0 + // // gl_rmath.c // @@ -492,7 +493,7 @@ void Matrix4x4_CreateScale3( matrix4x4 out, float x, float y, float z ); void Matrix4x4_CreateProjection(matrix4x4 out, float xMax, float xMin, float yMax, float yMin, float zNear, float zFar); void Matrix4x4_CreateOrtho(matrix4x4 m, float xLeft, float xRight, float yBottom, float yTop, float zNear, float zFar); void Matrix4x4_CreateModelview( matrix4x4 out ); - +#if 0 // // gl_rmisc.c // diff --git a/r_main.c b/r_main.c index f2ce33bd..bc788275 100644 --- a/r_main.c +++ b/r_main.c @@ -240,7 +240,7 @@ static int R_TransEntityCompare( const cl_entity_t **a, const cl_entity_t **b ) return 0; } -#if 0 +#if 1 /* =============== @@ -465,7 +465,7 @@ R_SetupFrustum void R_SetupFrustum( void ) { #if 1 - ref_overview_t *ov = gEngfuncs.GetOverviewParms(); + //ref_overview_t *ov = gEngfuncs.GetOverviewParms(); /*if( RP_NORMALPASS() && ( ENGINE_GET_PARM( PARM_WATER_LEVEL ) >= 3 )) { @@ -497,8 +497,8 @@ R_SetupProjectionMatrix */ static void R_SetupProjectionMatrix( matrix4x4 m ) { -#if 0 - GLdouble xMin, xMax, yMin, yMax, zNear, zFar; +#if 1 + double xMin, xMax, yMin, yMax, zNear, zFar; if( RI.drawOrtho ) { @@ -529,7 +529,7 @@ R_SetupModelviewMatrix */ static void R_SetupModelviewMatrix( matrix4x4 m ) { -#if 0 +#if 1 Matrix4x4_CreateModelview( m ); Matrix4x4_ConcatRotate( m, -RI.viewangles[2], 1, 0, 0 ); Matrix4x4_ConcatRotate( m, -RI.viewangles[0], 0, 1, 0 ); @@ -1568,6 +1568,7 @@ void R_MarkLeaves (void) #endif + /* ================ R_RenderScene @@ -1593,6 +1594,11 @@ void R_RenderScene( void ) R_SetupFrame(); R_PushDlights(); + R_SetupModelviewMatrix( RI.worldviewMatrix ); + R_SetupProjectionMatrix( RI.projectionMatrix ); + + Matrix4x4_Concat( RI.worldviewProjectionMatrix, RI.projectionMatrix, RI.worldviewMatrix ); + // R_SetupGL( true ); //R_Clear( ~0 ); diff --git a/r_math.c b/r_math.c new file mode 100644 index 00000000..c60e09fa --- /dev/null +++ b/r_math.c @@ -0,0 +1,267 @@ +/* +gl_rmath.c - renderer mathlib +Copyright (C) 2010 Uncle Mike + +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 3 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. +*/ + +#include "r_local.h" +#include "mathlib.h" + +/* +======================================================================== + + Matrix4x4 operations (private to renderer) + +======================================================================== +*/ +void Matrix4x4_Concat( matrix4x4 out, const matrix4x4 in1, const matrix4x4 in2 ) +{ + out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + in1[0][2] * in2[2][0] + in1[0][3] * in2[3][0]; + out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] + in1[0][2] * in2[2][1] + in1[0][3] * in2[3][1]; + out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] + in1[0][2] * in2[2][2] + in1[0][3] * in2[3][2]; + out[0][3] = in1[0][0] * in2[0][3] + in1[0][1] * in2[1][3] + in1[0][2] * in2[2][3] + in1[0][3] * in2[3][3]; + out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] + in1[1][2] * in2[2][0] + in1[1][3] * in2[3][0]; + out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] + in1[1][2] * in2[2][1] + in1[1][3] * in2[3][1]; + out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] + in1[1][2] * in2[2][2] + in1[1][3] * in2[3][2]; + out[1][3] = in1[1][0] * in2[0][3] + in1[1][1] * in2[1][3] + in1[1][2] * in2[2][3] + in1[1][3] * in2[3][3]; + out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] + in1[2][2] * in2[2][0] + in1[2][3] * in2[3][0]; + out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] + in1[2][2] * in2[2][1] + in1[2][3] * in2[3][1]; + out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] + in1[2][2] * in2[2][2] + in1[2][3] * in2[3][2]; + out[2][3] = in1[2][0] * in2[0][3] + in1[2][1] * in2[1][3] + in1[2][2] * in2[2][3] + in1[2][3] * in2[3][3]; + out[3][0] = in1[3][0] * in2[0][0] + in1[3][1] * in2[1][0] + in1[3][2] * in2[2][0] + in1[3][3] * in2[3][0]; + out[3][1] = in1[3][0] * in2[0][1] + in1[3][1] * in2[1][1] + in1[3][2] * in2[2][1] + in1[3][3] * in2[3][1]; + out[3][2] = in1[3][0] * in2[0][2] + in1[3][1] * in2[1][2] + in1[3][2] * in2[2][2] + in1[3][3] * in2[3][2]; + out[3][3] = in1[3][0] * in2[0][3] + in1[3][1] * in2[1][3] + in1[3][2] * in2[2][3] + in1[3][3] * in2[3][3]; +} + +/* +================ +Matrix4x4_CreateProjection + +NOTE: produce quake style world orientation +================ +*/ +void Matrix4x4_CreateProjection( matrix4x4 out, float xMax, float xMin, float yMax, float yMin, float zNear, float zFar ) +{ + out[0][0] = ( 2.0f * zNear ) / ( xMax - xMin ); + out[1][1] = ( 2.0f * zNear ) / ( yMax - yMin ); + out[2][2] = -( zFar + zNear ) / ( zFar - zNear ); + out[3][3] = out[0][1] = out[1][0] = out[3][0] = out[0][3] = out[3][1] = out[1][3] = 0.0f; + + out[2][0] = 0.0f; + out[2][1] = 0.0f; + out[0][2] = ( xMax + xMin ) / ( xMax - xMin ); + out[1][2] = ( yMax + yMin ) / ( yMax - yMin ); + out[3][2] = -1.0f; + out[2][3] = -( 2.0f * zFar * zNear ) / ( zFar - zNear ); +} + +void Matrix4x4_CreateOrtho( matrix4x4 out, float xLeft, float xRight, float yBottom, float yTop, float zNear, float zFar ) +{ + out[0][0] = 2.0f / (xRight - xLeft); + out[1][1] = 2.0f / (yTop - yBottom); + out[2][2] = -2.0f / (zFar - zNear); + out[3][3] = 1.0f; + out[0][1] = out[0][2] = out[1][0] = out[1][2] = out[3][0] = out[3][1] = out[3][2] = 0.0f; + + out[2][0] = 0.0f; + out[2][1] = 0.0f; + out[0][3] = -(xRight + xLeft) / (xRight - xLeft); + out[1][3] = -(yTop + yBottom) / (yTop - yBottom); + out[2][3] = -(zFar + zNear) / (zFar - zNear); +} + +/* +================ +Matrix4x4_CreateModelview + +NOTE: produce quake style world orientation +================ +*/ +void Matrix4x4_CreateModelview( matrix4x4 out ) +{ + out[0][0] = out[1][1] = out[2][2] = 0.0f; + out[3][0] = out[0][3] = 0.0f; + out[3][1] = out[1][3] = 0.0f; + out[3][2] = out[2][3] = 0.0f; + out[3][3] = 1.0f; + out[1][0] = out[0][2] = out[2][1] = 0.0f; + out[2][0] = out[0][1] = -1.0f; + out[1][2] = 1.0f; +} + +void Matrix4x4_ToArrayFloatGL( const matrix4x4 in, float out[16] ) +{ + out[ 0] = in[0][0]; + out[ 1] = in[1][0]; + out[ 2] = in[2][0]; + out[ 3] = in[3][0]; + out[ 4] = in[0][1]; + out[ 5] = in[1][1]; + out[ 6] = in[2][1]; + out[ 7] = in[3][1]; + out[ 8] = in[0][2]; + out[ 9] = in[1][2]; + out[10] = in[2][2]; + out[11] = in[3][2]; + out[12] = in[0][3]; + out[13] = in[1][3]; + out[14] = in[2][3]; + out[15] = in[3][3]; +} + +void Matrix4x4_FromArrayFloatGL( matrix4x4 out, const float in[16] ) +{ + out[0][0] = in[0]; + out[1][0] = in[1]; + out[2][0] = in[2]; + out[3][0] = in[3]; + out[0][1] = in[4]; + out[1][1] = in[5]; + out[2][1] = in[6]; + out[3][1] = in[7]; + out[0][2] = in[8]; + out[1][2] = in[9]; + out[2][2] = in[10]; + out[3][2] = in[11]; + out[0][3] = in[12]; + out[1][3] = in[13]; + out[2][3] = in[14]; + out[3][3] = in[15]; +} + +void Matrix4x4_CreateTranslate( matrix4x4 out, float x, float y, float z ) +{ + out[0][0] = 1.0f; + out[0][1] = 0.0f; + out[0][2] = 0.0f; + out[0][3] = x; + out[1][0] = 0.0f; + out[1][1] = 1.0f; + out[1][2] = 0.0f; + out[1][3] = y; + out[2][0] = 0.0f; + out[2][1] = 0.0f; + out[2][2] = 1.0f; + out[2][3] = z; + out[3][0] = 0.0f; + out[3][1] = 0.0f; + out[3][2] = 0.0f; + out[3][3] = 1.0f; +} + +void Matrix4x4_CreateRotate( matrix4x4 out, float angle, float x, float y, float z ) +{ + float len, c, s; + + len = x * x + y * y + z * z; + if( len != 0.0f ) len = 1.0f / sqrt( len ); + x *= len; + y *= len; + z *= len; + + angle *= (-M_PI / 180.0f); + SinCos( angle, &s, &c ); + + out[0][0]=x * x + c * (1 - x * x); + out[0][1]=x * y * (1 - c) + z * s; + out[0][2]=z * x * (1 - c) - y * s; + out[0][3]=0.0f; + out[1][0]=x * y * (1 - c) - z * s; + out[1][1]=y * y + c * (1 - y * y); + out[1][2]=y * z * (1 - c) + x * s; + out[1][3]=0.0f; + out[2][0]=z * x * (1 - c) + y * s; + out[2][1]=y * z * (1 - c) - x * s; + out[2][2]=z * z + c * (1 - z * z); + out[2][3]=0.0f; + out[3][0]=0.0f; + out[3][1]=0.0f; + out[3][2]=0.0f; + out[3][3]=1.0f; +} + +void Matrix4x4_CreateScale( matrix4x4 out, float x ) +{ + out[0][0] = x; + out[0][1] = 0.0f; + out[0][2] = 0.0f; + out[0][3] = 0.0f; + out[1][0] = 0.0f; + out[1][1] = x; + out[1][2] = 0.0f; + out[1][3] = 0.0f; + out[2][0] = 0.0f; + out[2][1] = 0.0f; + out[2][2] = x; + out[2][3] = 0.0f; + out[3][0] = 0.0f; + out[3][1] = 0.0f; + out[3][2] = 0.0f; + out[3][3] = 1.0f; +} + +void Matrix4x4_CreateScale3( matrix4x4 out, float x, float y, float z ) +{ + out[0][0] = x; + out[0][1] = 0.0f; + out[0][2] = 0.0f; + out[0][3] = 0.0f; + out[1][0] = 0.0f; + out[1][1] = y; + out[1][2] = 0.0f; + out[1][3] = 0.0f; + out[2][0] = 0.0f; + out[2][1] = 0.0f; + out[2][2] = z; + out[2][3] = 0.0f; + out[3][0] = 0.0f; + out[3][1] = 0.0f; + out[3][2] = 0.0f; + out[3][3] = 1.0f; +} + +void Matrix4x4_ConcatTranslate( matrix4x4 out, float x, float y, float z ) +{ + matrix4x4 base, temp; + + Matrix4x4_Copy( base, out ); + Matrix4x4_CreateTranslate( temp, x, y, z ); + Matrix4x4_Concat( out, base, temp ); +} + +void Matrix4x4_ConcatRotate( matrix4x4 out, float angle, float x, float y, float z ) +{ + matrix4x4 base, temp; + + Matrix4x4_Copy( base, out ); + Matrix4x4_CreateRotate( temp, angle, x, y, z ); + Matrix4x4_Concat( out, base, temp ); +} + +void Matrix4x4_ConcatScale( matrix4x4 out, float x ) +{ + matrix4x4 base, temp; + + Matrix4x4_Copy( base, out ); + Matrix4x4_CreateScale( temp, x ); + Matrix4x4_Concat( out, base, temp ); +} + +void Matrix4x4_ConcatScale3( matrix4x4 out, float x, float y, float z ) +{ + matrix4x4 base, temp; + + Matrix4x4_Copy( base, out ); + Matrix4x4_CreateScale3( temp, x, y, z ); + Matrix4x4_Concat( out, base, temp ); +} diff --git a/r_sprite.c b/r_sprite.c index 91fd76e3..f28816a0 100644 --- a/r_sprite.c +++ b/r_sprite.c @@ -699,6 +699,7 @@ qboolean R_SpriteOccluded( cl_entity_t *e, vec3_t origin, float *pscale ) { float blend; vec3_t v; + //return false; TriWorldToScreen( origin, v ); diff --git a/r_triapi.c b/r_triapi.c index db971c94..386fb1c1 100644 --- a/r_triapi.c +++ b/r_triapi.c @@ -345,7 +345,7 @@ void TriVertex3f( float x, float y, float z ) } #endif } -void R_AliasWorldToScreen( const float *v, float *out ); + /* ============= TriWorldToScreen @@ -357,15 +357,14 @@ int TriWorldToScreen( const float *world, float *screen ) { int retval; - R_AliasWorldToScreen( world, screen ); - retval = 0; - + retval = R_WorldToScreen( world, screen ); screen[0] = 0.5f * screen[0] * (float)RI.viewport[2]; screen[1] = -0.5f * screen[1] * (float)RI.viewport[3]; screen[0] += 0.5f * (float)RI.viewport[2]; screen[1] += 0.5f * (float)RI.viewport[3]; + return retval; } From ebd1da2730b0d135d900682acfebcc001e2e29f1 Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 4 Apr 2019 02:00:24 +0700 Subject: [PATCH 064/115] ref_soft: Transform dlights for entitites --- r_edge.c | 7 +++++++ r_main.c | 18 ++++++++++++------ r_surf.c | 8 ++++---- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/r_edge.c b/r_edge.c index 4da740af..e8b73f8d 100644 --- a/r_edge.c +++ b/r_edge.c @@ -1115,12 +1115,19 @@ void D_SolidSurf (surf_t *s) R_RotateBmodel (); // FIXME: don't mess with the frustum, // make entity passed in + // setup dlight transform + if( s->msurf && s->msurf->dlightframe == tr.framecount ) + { + Matrix4x4_CreateFromEntity( RI.objectMatrix, RI.currententity->angles, RI.currententity->origin, 1 ); + tr.modelviewIdentity = false; + } } else { if( alphaspans ) return; RI.currententity = gEngfuncs.GetEntityByIndex(0); //r_worldentity; + tr.modelviewIdentity = true; } pface = s->msurf; diff --git a/r_main.c b/r_main.c index bc788275..e1cf762a 100644 --- a/r_main.c +++ b/r_main.c @@ -1196,16 +1196,18 @@ void R_DrawBEntitiesOnList (void) for( k = 0; k < MAX_DLIGHTS; k++ ) { dlight_t *l = gEngfuncs.GetDynamicLight( k ); + vec3_t origin_l, oldorigin; if( l->die < gpGlobals->time || !l->radius ) continue; - /*VectorCopy( l->origin, oldorigin ); // save lightorigin + VectorCopy( l->origin, oldorigin ); // save lightorigin + Matrix4x4_CreateFromEntity( RI.objectMatrix, RI.currententity->angles, RI.currententity->origin, 1 ); Matrix4x4_VectorITransform( RI.objectMatrix, l->origin, origin_l ); VectorCopy( origin_l, l->origin ); // move light in bmodel space - R_MarkLights( l, 1<nodes + clmodel->hulls[0].firstclipnode ); - VectorCopy( oldorigin, l->origin ); // restore lightorigin*/ R_MarkLights( l, 1<nodes + RI.currentmodel->hulls[0].firstclipnode ); + VectorCopy( oldorigin, l->origin ); // restore lightorigin*/ + //R_MarkLights( l, 1<nodes + RI.currentmodel->hulls[0].firstclipnode ); } // RI.currentmodel = tr.draw_list->solid_entities[i]->model; @@ -1350,16 +1352,19 @@ void R_DrawBrushModel(cl_entity_t *pent) for( k = 0; k < MAX_DLIGHTS; k++ ) { dlight_t *l = gEngfuncs.GetDynamicLight( k ); + vec3_t origin_l, oldorigin; if( l->die < gpGlobals->time || !l->radius ) continue; - /*VectorCopy( l->origin, oldorigin ); // save lightorigin + VectorCopy( l->origin, oldorigin ); // save lightorigin + Matrix4x4_CreateFromEntity( RI.objectMatrix, RI.currententity->angles, RI.currententity->origin, 1 ); Matrix4x4_VectorITransform( RI.objectMatrix, l->origin, origin_l ); + tr.modelviewIdentity = false; VectorCopy( origin_l, l->origin ); // move light in bmodel space - R_MarkLights( l, 1<nodes + clmodel->hulls[0].firstclipnode ); - VectorCopy( oldorigin, l->origin ); // restore lightorigin*/ R_MarkLights( l, 1<nodes + RI.currentmodel->hulls[0].firstclipnode ); + VectorCopy( oldorigin, l->origin ); // restore lightorigin*/ + //R_MarkLights( l, 1<nodes + RI.currentmodel->hulls[0].firstclipnode ); } // RI.currentmodel = tr.draw_list->solid_entities[i]->model; @@ -1598,6 +1603,7 @@ void R_RenderScene( void ) R_SetupProjectionMatrix( RI.projectionMatrix ); Matrix4x4_Concat( RI.worldviewProjectionMatrix, RI.projectionMatrix, RI.worldviewMatrix ); + tr.modelviewIdentity = true; // R_SetupGL( true ); //R_Clear( ~0 ); diff --git a/r_surf.c b/r_surf.c index 633657e4..b8c0bde4 100644 --- a/r_surf.c +++ b/r_surf.c @@ -105,10 +105,10 @@ void R_AddDynamicLights( msurface_t *surf ) dl = gEngfuncs.GetDynamicLight( lnum ); // transform light origin to local bmodel space - //if( !tr.modelviewIdentity ) - //Matrix4x4_VectorITransform( RI.objectMatrix, dl->origin, origin_l ); - //else - VectorCopy( dl->origin, origin_l ); + if( !tr.modelviewIdentity ) + Matrix4x4_VectorITransform( RI.objectMatrix, dl->origin, origin_l ); + else + VectorCopy( dl->origin, origin_l ); rad = dl->radius; dist = PlaneDiff( origin_l, surf->plane ); From e0cd5edddbdfa18d1a10508699c97a60bfae1b00 Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 4 Apr 2019 02:38:57 +0700 Subject: [PATCH 065/115] ref_soft: Ignore non-horizontal water planes --- r_bsp.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/r_bsp.c b/r_bsp.c index a9640f22..01229af4 100644 --- a/r_bsp.c +++ b/r_bsp.c @@ -663,6 +663,13 @@ void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel, mnode_t *topnode) for (i=0 ; iflags, SURF_DRAWTURB ) && !ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE )) + { + if( psurf->plane->type != PLANE_Z && !FBitSet( RI.currententity->curstate.effects, EF_WATERSIDES )) + continue; + if( r_entorigin[2] + pmodel->mins[2] + 1.0 >= psurf->plane->dist ) + continue; + } // find which side of the node we are on pplane = psurf->plane; @@ -738,6 +745,13 @@ void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags, mnode_t *topnode) for (i=0 ; iflags, SURF_DRAWTURB ) && !ENGINE_GET_PARM( PARM_QUAKE_COMPATIBLE )) + { + if( psurf->plane->type != PLANE_Z && !FBitSet( RI.currententity->curstate.effects, EF_WATERSIDES )) + continue; + if( r_entorigin[2] + pmodel->mins[2] + 1.0 >= psurf->plane->dist ) + continue; + } // find which side of the node we are on pplane = psurf->plane; From cefe42fd661bd74beab1bcbc34a78f6a63e53170 Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 4 Apr 2019 02:56:29 +0700 Subject: [PATCH 066/115] ref_soft: Fix R_NewMap, prevent crashes on changelevel/restart --- r_decals.c | 2 +- r_main.c | 69 ++++++++++++++++++++++++++++++------------------------ 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/r_decals.c b/r_decals.c index 8aba9c42..15c6748d 100644 --- a/r_decals.c +++ b/r_decals.c @@ -1173,7 +1173,7 @@ int R_CreateDecalList( decallist_t *pList ) int total = 0; int i, depth; - return 0; // crash on changelevel. API bug? +// return 0; // crash on changelevel. API bug? if( WORLDMODEL ) { diff --git a/r_main.c b/r_main.c index e1cf762a..07fbd91c 100644 --- a/r_main.c +++ b/r_main.c @@ -1822,44 +1822,51 @@ R_NewMap */ void R_NewMap (void) { - r_viewcluster = -1; + int i; + r_viewcluster = -1; + R_ClearDecals(); // clear all level decals + R_StudioResetPlayerModels(); - D_FlushCaches( true ); + D_FlushCaches( true ); - r_cnumsurfs = sw_maxsurfs->value; + r_cnumsurfs = sw_maxsurfs->value; - if (r_cnumsurfs <= MINSURFACES) - r_cnumsurfs = MINSURFACES; + if (r_cnumsurfs <= MINSURFACES) + r_cnumsurfs = MINSURFACES; - if (r_cnumsurfs > NUMSTACKSURFACES) - { - surfaces = Mem_Calloc (r_temppool, r_cnumsurfs * sizeof(surf_t)); - surface_p = surfaces; - surf_max = &surfaces[r_cnumsurfs]; - r_surfsonstack = false; - // surface 0 doesn't really exist; it's just a dummy because index 0 - // is used to indicate no edge attached to surface - surfaces--; - R_SurfacePatch (); - } - else - { - r_surfsonstack = true; - } + if (r_cnumsurfs > NUMSTACKSURFACES) + { + surfaces = Mem_Calloc (r_temppool, r_cnumsurfs * sizeof(surf_t)); + surface_p = surfaces; + surf_max = &surfaces[r_cnumsurfs]; + r_surfsonstack = false; + // surface 0 doesn't really exist; it's just a dummy because index 0 + // is used to indicate no edge attached to surface + surfaces--; + R_SurfacePatch (); + } + else + { + r_surfsonstack = true; + } - r_numallocatededges = sw_maxedges->value; + r_numallocatededges = sw_maxedges->value; - if (r_numallocatededges < MINEDGES) - r_numallocatededges = MINEDGES; + if (r_numallocatededges < MINEDGES) + r_numallocatededges = MINEDGES; - if (r_numallocatededges <= NUMSTACKEDGES) - { - auxedges = NULL; - } - else - { - auxedges = malloc (r_numallocatededges * sizeof(edge_t)); - } + if (r_numallocatededges <= NUMSTACKEDGES) + { + auxedges = NULL; + } + else + { + auxedges = malloc (r_numallocatededges * sizeof(edge_t)); + } + + // clear out efrags in case the level hasn't been reloaded + for( i = 0; i < WORLDMODEL->numleafs; i++ ) + WORLDMODEL->leafs[i+1].efrags = NULL; } /* From c08c35df698bcd142c99b49e639f4862bc394bab Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 4 Apr 2019 04:44:06 +0700 Subject: [PATCH 067/115] ref_soft: FillRGBA, FillRGBABlend --- r_context.c | 8 ++++-- r_draw.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++--- r_local.h | 2 +- r_misc.c | 2 -- 4 files changed, 82 insertions(+), 8 deletions(-) diff --git a/r_context.c b/r_context.c index b9e32f1d..69855083 100644 --- a/r_context.c +++ b/r_context.c @@ -106,7 +106,9 @@ CL_FillRGBA */ static void CL_FillRGBA( float _x, float _y, float _w, float _h, int r, int g, int b, int a ) { - + vid.rendermode = kRenderTransAdd; + _TriColor4ub(r,g,b,a); + Draw_Fill(_x,_y,_w,_h); } /* @@ -117,7 +119,9 @@ pfnFillRGBABlend */ static void GAME_EXPORT CL_FillRGBABlend( float _x, float _y, float _w, float _h, int r, int g, int b, int a ) { - + vid.rendermode = kRenderTransAlpha; + _TriColor4ub(r,g,b,a); + Draw_Fill(_x,_y,_w,_h); } diff --git a/r_draw.c b/r_draw.c index 8cd3c79b..06117f3b 100644 --- a/r_draw.c +++ b/r_draw.c @@ -199,10 +199,82 @@ void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, f R_DrawStretchPicImplementation(x,y,w,h, pic->width * s1, pic->height * t1, pic->width * s2, pic->height * t2, pic); } -void Draw_Fill (int x, int y, int w, int h, int c) +void Draw_Fill (int x, int y, int w, int h) { - // todo: color - R_DrawStretchPicImplementation(x,y,w,h, 0, 0, 12, 1, tr.whiteTexture ); + pixel_t *dest; + unsigned int v, u; + unsigned int height; + int skip; + pixel_t src = vid.color; + int alpha = vid.alpha; + + if( x < 0 ) + x = 0; + + if( x + w > vid.width ) + w = vid.width - x; + + if( y + h > vid.height ) + h = vid.height - y; + + height = h; + if (y < 0) + { + skip = -y; + height += y; + y = 0; + } + else + skip = 0; + + dest = vid.buffer + y * vid.rowbytes + x; + + #pragma omp parallel for schedule(static) + for (v=0 ; v>16]; + f += fstep; + dest[u+1] = source[f>>16]; + f += fstep; + dest[u+2] = source[f>>16]; + f += fstep; + dest[u+3] = source[f>>16]; + f += fstep; + } +#else + for (u=0 ; u>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 0); + } + else if( alpha < 7) // && (vid.rendermode == kRenderTransAlpha || vid.rendermode == kRenderTransTexture ) ) + { + pixel_t screen = dest[u]; // | 0xff & screen & src ; + dest[u] = BLEND_ALPHA( alpha, src, screen);//vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) >> 3 | ((src & 0xff) >> 3); + + } + else + dest[u] = src; + + } +#endif + } + dest += vid.rowbytes; + } } /* diff --git a/r_local.h b/r_local.h index 7906dfc5..485a0a04 100644 --- a/r_local.h +++ b/r_local.h @@ -1252,7 +1252,7 @@ void D_FlushCaches( qboolean newmap ); // // r_draw.c // -void Draw_Fill (int x, int y, int w, int h, int c); +void Draw_Fill (int x, int y, int w, int h); // // r_misc.c diff --git a/r_misc.c b/r_misc.c index e4e3f3fe..7bbb66e2 100644 --- a/r_misc.c +++ b/r_misc.c @@ -111,8 +111,6 @@ void D_ViewChanged (void) if ( !RI.drawWorld ) { memset( d_pzbuffer, 0xff, vid.width * vid.height * sizeof( d_pzbuffer[0] ) ); - // newrefdef - Draw_Fill( 0, 0, gpGlobals->width, gpGlobals->height,( int ) sw_clearcolor->value & 0xff ); } D_Patch (); From 033a9476313e7c130b578103580f3954327bfe21 Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 4 Apr 2019 09:38:17 +0700 Subject: [PATCH 068/115] ref_soft: set minor bits in alpha map to make it more accurate --- r_glblit.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/r_glblit.c b/r_glblit.c index 1e3a5ea1..9c7577f8 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -205,7 +205,7 @@ void R_BuildBlendMaps() for( i = 0; i < 1024; i++ ) { unsigned int r, g, b; - uint color = i << 6; + uint color = i << 6 | BIT(5) | BIT(4) | BIT(3); uint m = color >> 8; uint j = color & 0xff; @@ -228,9 +228,9 @@ void R_BuildBlendMaps() unsigned int a = k + 1; - r = r1 * (7 - a) / 7 + (r2 << 2) * a / 7; - g = g1 * (7 - a) / 7 + (g2 << 3) * a / 7; - b = b1 * (7 - a) / 7 + (b2 << 3) * a / 7; + r = r1 * (7 - a) / 7 + (r2 << 2 | BIT(2)) * a / 7; + g = g1 * (7 - a) / 7 + (g2 << 3 | MASK(2)) * a / 7; + b = b1 * (7 - a) / 7 + (b2 << 3 | BIT(3)) * a / 7; ASSERT( b < 32 ); major = (((r >> 2) & MASK(3)) << 5) |( (( (g >> 3) & MASK(3)) << 2 ) )| (((b >> 3) & MASK(2))); From 500ff629bfaa112d2b4008521b3095a48580174f Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 4 Apr 2019 10:01:11 +0700 Subject: [PATCH 069/115] ref_soft: decrease alpha to make water visible again --- r_glblit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/r_glblit.c b/r_glblit.c index 9c7577f8..0c2fdf41 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -225,12 +225,12 @@ void R_BuildBlendMaps() for( k = 0; k < 3; k++ ) { unsigned int major, minor; - unsigned int a = k + 1; + unsigned int a = k + 2; r = r1 * (7 - a) / 7 + (r2 << 2 | BIT(2)) * a / 7; g = g1 * (7 - a) / 7 + (g2 << 3 | MASK(2)) * a / 7; - b = b1 * (7 - a) / 7 + (b2 << 3 | BIT(3)) * a / 7; + b = b1 * (7 - a) / 7 + (b2 << 3 | MASK(2)) * a / 7; ASSERT( b < 32 ); major = (((r >> 2) & MASK(3)) << 5) |( (( (g >> 3) & MASK(3)) << 2 ) )| (((b >> 3) & MASK(2))); From 338b404055ec3ca02fd8e6121ca0510ae9a3b4fc Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 4 Apr 2019 10:27:18 +0700 Subject: [PATCH 070/115] ref_soft: clamp alpha values --- r_edge.c | 11 +++++++++-- r_glblit.c | 7 +++++++ r_scan.c | 10 ++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/r_edge.c b/r_edge.c index e8b73f8d..1ac231a4 100644 --- a/r_edge.c +++ b/r_edge.c @@ -996,6 +996,8 @@ Normal surface cached, texture mapped surface */ void D_AlphaSurf (surf_t *s) { + int alpha; + d_zistepu = s->d_zistepu; d_zistepv = s->d_zistepv; d_ziorigin = s->d_ziorigin; @@ -1052,13 +1054,16 @@ void D_AlphaSurf (surf_t *s) miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip * pface->texinfo->mipadjust); } #endif + alpha = RI.currententity->curstate.renderamt * 7 / 255; + if( alpha <= 0 && RI.currententity->curstate.renderamt > 0 ) + alpha = 1; if (s->flags & SURF_DRAWTURB ) { cacheblock = R_GetTexture(pface->texinfo->texture->gl_texturenum)->pixels[0]; cachewidth = 64; D_CalcGradients (pface); - TurbulentZ8( s->spans, RI.currententity->curstate.renderamt * 7 / 255 ); + TurbulentZ8( s->spans, alpha); } else { @@ -1070,12 +1075,14 @@ void D_AlphaSurf (surf_t *s) D_CalcGradients (pface); + + if( RI.currententity->curstate.rendermode == kRenderTransAlpha ) D_AlphaSpans16(s->spans); else if( RI.currententity->curstate.rendermode == kRenderTransAdd ) D_AddSpans16(s->spans); else - D_BlendSpans16(s->spans, RI.currententity->curstate.renderamt * 7 / 255 ); + D_BlendSpans16(s->spans, alpha ); } VectorCopy (world_transformed_modelorg, diff --git a/r_glblit.c b/r_glblit.c index 0c2fdf41..a73cac59 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -231,6 +231,13 @@ void R_BuildBlendMaps() r = r1 * (7 - a) / 7 + (r2 << 2 | BIT(2)) * a / 7; g = g1 * (7 - a) / 7 + (g2 << 3 | MASK(2)) * a / 7; b = b1 * (7 - a) / 7 + (b2 << 3 | MASK(2)) * a / 7; + if( r > MASK(5) ) + r = MASK(5); + if( g > MASK(6) ) + g = MASK(6); + if( b > MASK(5) ) + b = MASK(5); + ASSERT( b < 32 ); major = (((r >> 2) & MASK(3)) << 5) |( (( (g >> 3) & MASK(3)) << 2 ) )| (((b >> 3) & MASK(2))); diff --git a/r_scan.c b/r_scan.c index fa5855c3..18a72ac9 100644 --- a/r_scan.c +++ b/r_scan.c @@ -297,6 +297,11 @@ void TurbulentZ8 (espan_t *pspan, int alpha1) float sdivz16stepu, tdivz16stepu, zi16stepu; alpha = alpha1; + if( alpha > 7 ) + alpha = 7; + if( alpha == 0 ) + return; + r_turb_turb = sintable + ((int)(gpGlobals->time*SPEED)&(CYCLE-1)); r_turb_sstep = 0; // keep compiler happy @@ -960,6 +965,11 @@ void D_BlendSpans16 (espan_t *pspan, int alpha) int izi, izistep; short *pz; + if( alpha > 7 ) + alpha = 7; + if( alpha == 0 ) + return; + sstep = 0; // keep compiler happy tstep = 0; // ditto From 4aa5778606bf46871f55d1debb5a7ccc69cd6246 Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 4 Apr 2019 10:37:41 +0700 Subject: [PATCH 071/115] ref_soft: Alpha support for additive/glow --- r_triapi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/r_triapi.c b/r_triapi.c index 386fb1c1..f623512e 100644 --- a/r_triapi.c +++ b/r_triapi.c @@ -147,7 +147,8 @@ void _TriColor4f( float rr, float gg, float bb, float aa ) unsigned short r,g,b; unsigned int major, minor; - + if( vid.rendermode == kRenderTransAdd || vid.rendermode == kRenderGlow ) + rr *= aa, gg *= aa, bb *= aa; //gEngfuncs.Con_Printf("%d\n", vid.alpha); From 9fbb8a8201a1d6c784e7a29e58f338e2058888f3 Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 4 Apr 2019 10:51:11 +0700 Subject: [PATCH 072/115] ref_soft: Add alpha test for brushes to all rendermodes --- r_scan.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/r_scan.c b/r_scan.c index 18a72ac9..c0e7838b 100644 --- a/r_scan.c +++ b/r_scan.c @@ -1090,9 +1090,12 @@ void D_BlendSpans16 (espan_t *pspan, int alpha) btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth); - if( alpha != 7 ) - btemp = BLEND_ALPHA( alpha, btemp, *pdest); - *pdest = btemp; + if( btemp != TRANSPARENT_COLOR ) + { + if( alpha != 7 ) + btemp = BLEND_ALPHA( alpha, btemp, *pdest); + *pdest = btemp; + } //*pz = izi >> 16; } pdest++; @@ -1128,9 +1131,12 @@ void D_BlendSpans16 (espan_t *pspan, int alpha) btemp = *(pbase + idiths + iditht * cachewidth); - if( alpha != 7 ) - btemp = BLEND_ALPHA( alpha, btemp, *pdest); - *pdest = btemp; + if( btemp != TRANSPARENT_COLOR ) + { + if( alpha != 7 ) + btemp = BLEND_ALPHA( alpha, btemp, *pdest); + *pdest = btemp; + } //*pz = izi >> 16; } pdest++; @@ -1286,8 +1292,11 @@ void D_AddSpans16 (espan_t *pspan) btemp = *(pbase + (s >> 16) + (t >> 16) * cachewidth); - btemp = BLEND_ADD( btemp, *pdest); - *pdest = btemp; + if( btemp != TRANSPARENT_COLOR ) + { + btemp = BLEND_ADD( btemp, *pdest); + *pdest = btemp; + } //*pz = izi >> 16; } pdest++; @@ -1323,8 +1332,11 @@ void D_AddSpans16 (espan_t *pspan) btemp = *(pbase + idiths + iditht * cachewidth); - btemp = BLEND_ADD( btemp, *pdest); - *pdest = btemp; + if( btemp != TRANSPARENT_COLOR ) + { + btemp = BLEND_ADD( btemp, *pdest); + *pdest = btemp; + } //*pz = izi >> 16; } pdest++; From 7f1491f8840be49bc1a7b9e16dafe4f10dc9a0dd Mon Sep 17 00:00:00 2001 From: mittorn Date: Fri, 5 Apr 2019 15:56:05 +0700 Subject: [PATCH 073/115] ref_soft: Try fix crash on changelevel --- r_main.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/r_main.c b/r_main.c index 07fbd91c..7601f76f 100644 --- a/r_main.c +++ b/r_main.c @@ -208,7 +208,7 @@ static int R_TransEntityCompare( const cl_entity_t **a, const cl_entity_t **b ) rendermode2 = R_GetEntityRenderMode( ent2 ); // sort by distance - if( ent1->model->type != mod_brush || rendermode1 != kRenderTransAlpha ) + if( ent1->model && ent1->model->type != mod_brush || rendermode1 != kRenderTransAlpha ) { VectorAverage( ent1->model->mins, ent1->model->maxs, org ); VectorAdd( ent1->origin, org, org ); @@ -217,7 +217,7 @@ static int R_TransEntityCompare( const cl_entity_t **a, const cl_entity_t **b ) } else dist1 = 1000000000; - if( ent2->model->type != mod_brush || rendermode2 != kRenderTransAlpha ) + if( ent1->model && ent2->model->type != mod_brush || rendermode2 != kRenderTransAlpha ) { VectorAverage( ent2->model->mins, ent2->model->maxs, org ); VectorAdd( ent2->origin, org, org ); @@ -1824,6 +1824,12 @@ void R_NewMap (void) { int i; r_viewcluster = -1; + + tr.draw_list->num_solid_entities = 0; + tr.draw_list->num_trans_entities = 0; + tr.draw_list->num_beam_entities = 0; + tr.draw_list->num_edge_entities = 0; + R_ClearDecals(); // clear all level decals R_StudioResetPlayerModels(); From b584e89d901991529c55126275b84b8c0bcbd1d7 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 6 Apr 2019 14:40:08 +0700 Subject: [PATCH 074/115] ref_soft: add bounds checking in triangle render --- r_decals.c | 2 +- r_edge.c | 2 +- r_image.c | 7 ++- r_polyse.c | 135 +++++++++++++++++++++++++++++++++++++++++++++++------ r_surf.c | 18 ++++--- 5 files changed, 139 insertions(+), 25 deletions(-) diff --git a/r_decals.c b/r_decals.c index 15c6748d..27716742 100644 --- a/r_decals.c +++ b/r_decals.c @@ -519,7 +519,7 @@ glpoly_t *R_DecalCreatePoly( decalinfo_t *decalinfo, decal_t *pdecal, msurface_t float *v; int i; - return; + return NULL; if( pdecal->polys ) // already created? return pdecal->polys; diff --git a/r_edge.c b/r_edge.c index 1ac231a4..4c9a3d16 100644 --- a/r_edge.c +++ b/r_edge.c @@ -680,7 +680,7 @@ void R_ScanEdges (void) edge_aftertail.prev = &edge_tail; // FIXME: do we need this now that we clamp x in r_draw.c? - edge_sentinel.u = 2000 << 24; // make sure nothing sorts past this + edge_sentinel.u = 2000 << 20; // make sure nothing sorts past this edge_sentinel.prev = &edge_aftertail; // diff --git a/r_image.c b/r_image.c index 2d34959d..462ec3b5 100644 --- a/r_image.c +++ b/r_image.c @@ -571,12 +571,15 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) //GL_TextureImageRAW( tex, i, j, width, height, tex->depth, pic->type, data ); // increase size to workaround triangle renderer bugs // it seems to assume memory readable. maybe it was pointed to WAD? - tex->pixels[j] = (byte*)Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 1024 ) + 512; + //tex->pixels[j] = (byte*)Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 1024 ) + 512; + tex->pixels[j] = (byte*)Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) ); + + //memset( (byte*)tex->pixels[j] - 512, 0xFF, 512 ); //memset( (byte*)tex->pixels[j] + width * height * sizeof(pixel_t), 0xFF, 512 ); if( j == 0 && tex->flags & TF_HAS_ALPHA ) - tex->alpha_pixels = (byte*)Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 256 ) + 128; + tex->alpha_pixels = (byte*)Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) ); for(i = 0; i < height * width; i++ ) { diff --git a/r_polyse.c b/r_polyse.c index cd23a7f0..1bbafd14 100644 --- a/r_polyse.c +++ b/r_polyse.c @@ -116,12 +116,12 @@ void R_PolysetDrawSpans8_33 (spanpackage_t *pspanpackage); void R_PolysetDrawSpans8_66 (spanpackage_t *pspanpackage); void R_PolysetDrawSpans8_Opaque (spanpackage_t *pspanpackage); -void R_PolysetCalcGradients (int skinwidth); +qboolean R_PolysetCalcGradients(int skinwidth); void R_DrawNonSubdiv (void); void R_PolysetSetEdgeTable (void); void R_RasterizeAliasPolySmooth (void); void R_PolysetScanLeftEdge(int height); -void R_PolysetScanLeftEdge_C(int height); +qboolean R_PolysetScanLeftEdge_C(int height); /* ================ @@ -206,13 +206,61 @@ void R_DrawTriangle( void ) } } +/// TODO: fix this and do not check bounds in shader +static inline qboolean R_CheckBounds( void) +{ + //pixel_t *skin = r_affinetridesc.pskin; + +#if 0 // does not help. Quake 2 Developers, PLEASE FIX UR F***NG CODE!!! + + int lcount = errorterm >= 0?d_countextrastep:ubasestep; + pixel_t *lptex1, *lptex2, *lptex3, *lptex4; + + lcount+=2; + + if( lcount <= 0 ) + lcount = 2; + + lptex1 = d_ptex + a_ststepxwhole * lcount + ((a_sstepxfrac * lcount) >> 16) + ((a_tstepxfrac * lcount) >> 16)*r_affinetridesc.skinwidth; + lptex2 = d_ptex + a_ststepxwhole * lcount + ((a_sstepxfrac * lcount) >> 16); + lptex3 = d_ptex + a_ststepxwhole * lcount + ((a_tstepxfrac * lcount) >> 16)*r_affinetridesc.skinwidth; + lptex4 = d_ptex + a_ststepxwhole * lcount; + + + + + //if( lptex1 < skin || lptex1 > skin + r_affinetridesc.skinwidth * r_affinetridesc.skinheight ) + // return false; + // if( lptex2 < skin || lptex2 > skin + r_affinetridesc.skinwidth * r_affinetridesc.skinheight ) + // return false; + //if( lptex3 < skin || lptex3 > skin + r_affinetridesc.skinwidth * r_affinetridesc.skinheight ) + // return false; + // if( lptex4 < skin || lptex4 > skin + r_affinetridesc.skinwidth * r_affinetridesc.skinheight ) + // return false; + +#endif + //if( d_ptex - skin < 0 || d_ptex - ( skin + r_affinetridesc.skinwidth * r_affinetridesc.skinheight ) >= 0 ) + //return false; + + return true; +} + +static pixel_t *skinend; + +static inline qboolean R_DrawCheckBounds( pixel_t *lptex ) +{ + pixel_t *skin = r_affinetridesc.pskin; + if( lptex - skin < 0 || lptex - skinend >= 0 ) + return false; + return true; +} /* =================== R_PolysetScanLeftEdge_C ==================== */ -void R_PolysetScanLeftEdge_C(int height) +qboolean R_PolysetScanLeftEdge_C(int height) { do { @@ -228,8 +276,9 @@ void R_PolysetScanLeftEdge_C(int height) d_pedgespanpackage->light = d_light; d_pedgespanpackage->zi = d_zi; - if( d_pedgespanpackage->ptex - (pixel_t*)r_affinetridesc.pskin < 0 ) - d_pedgespanpackage->ptex = r_affinetridesc.pskin; + + if( !R_CheckBounds() ) + return false; d_pedgespanpackage++; @@ -274,6 +323,7 @@ void R_PolysetScanLeftEdge_C(int height) d_zi += d_zibasestep; } } while (--height); + return true; } /* @@ -638,7 +688,7 @@ done_with_steps: __asm mov a_ststepxwhole, eax } #else -void R_PolysetCalcGradients (int skinwidth) +qboolean R_PolysetCalcGradients (int skinwidth) { float xstepdenominv, ystepdenominv, t0, t1; float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20; @@ -648,6 +698,11 @@ void R_PolysetCalcGradients (int skinwidth) p10_minus_p20 = r_p1[0] - r_p2[0]; p11_minus_p21 = r_p1[1] - r_p2[1]; + /*printf("gradients for triangle\n"); + printf("%d %d %d %d %d %d\n" , r_p0[0], r_p0[1], r_p0[2] >> 16, r_p0[3] >> 16, r_p0[4], r_p0[5]); + printf("%d %d %d %d %d %d\n" , r_p1[0], r_p1[1], r_p1[2] >> 16, r_p1[3] >> 16, r_p1[4], r_p1[5]); + printf("%d %d %d %d %d %d\n\n", r_p2[0], r_p2[1], r_p2[2] >> 16, r_p2[3] >> 16, r_p2[4], r_p2[5]); +*/ xstepdenominv = 1.0 / (float)d_xdenom; ystepdenominv = -xstepdenominv; @@ -683,6 +738,16 @@ void R_PolysetCalcGradients (int skinwidth) r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv); + if( r_zistepx > INT_MAX / 2 ) + return false; + if( r_zistepx < INT_MIN / 2 ) + return false; + if( r_zistepy > INT_MAX / 2 ) + return false; + if( r_zistepy < INT_MIN / 2 ) + return false; + + //#if id386ALIAS #if id386 if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) @@ -699,7 +764,21 @@ void R_PolysetCalcGradients (int skinwidth) } //#endif + // do not allow big steps to make 512 byte extra bounds enough (still f**ng not) + if( r_sstepx <= -65535*8 ) + return false; + if( r_tstepx <= -65535*8) + return false; + if( r_sstepx >= 65535*8 ) + return false; + if( r_tstepx >= 65535*8 ) + return false; + a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16); + +// printf("%d %d %d %d\n",a_ststepxwhole, r_sstepx, r_tstepx, skinwidth ); + skinend = (pixel_t*)r_affinetridesc.pskin + r_affinetridesc.skinwidth * r_affinetridesc.skinheight; + return true; } #endif @@ -755,6 +834,9 @@ void R_PolysetDrawSpansBlended( spanpackage_t *pspanpackage) return; } #endif + if( !R_DrawCheckBounds( lptex ) ) + return; + pixel_t temp = *lptex;//vid.colormap[*lptex + ( llight & 0xFF00 )]; temp = BLEND_COLOR(temp, vid.color); @@ -830,6 +912,8 @@ void R_PolysetDrawSpansAdditive( spanpackage_t *pspanpackage) { if ((lzi >> 16) >= *lpz) { + if( !R_DrawCheckBounds( lptex ) ) + return; #if 0 if((int)(lptex - (pixel_t*)r_affinetridesc.pskin) > r_affinetridesc.skinwidth * r_affinetridesc.skinheight || (int)(lptex - (pixel_t*)r_affinetridesc.pskin) < 0 ) { @@ -909,6 +993,8 @@ void R_PolysetDrawSpansGlow( spanpackage_t *pspanpackage) { //if ((lzi >> 16) >= *lpz) { + if( !R_DrawCheckBounds( lptex ) ) + return; #if 0 if((int)(lptex - (pixel_t*)r_affinetridesc.pskin) > r_affinetridesc.skinwidth * r_affinetridesc.skinheight || (int)(lptex - (pixel_t*)r_affinetridesc.pskin) < 0 ) { @@ -988,6 +1074,8 @@ void R_PolysetDrawSpansTextureBlended( spanpackage_t *pspanpackage) { if ((lzi >> 16) >= *lpz) { + if( !R_DrawCheckBounds( lptex ) ) + return; #if 0 if((int)(lptex - (pixel_t*)r_affinetridesc.pskin) > r_affinetridesc.skinwidth * r_affinetridesc.skinheight || (int)(lptex - (pixel_t*)r_affinetridesc.pskin) < 0 ) { @@ -1414,6 +1502,8 @@ void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) { if ((lzi >> 16) >= *lpz) { + if( !R_DrawCheckBounds( lptex ) ) + return; //PGM /*if(r_newrefdef.rdflags & RDF_IRGOGGLES && RI.currententity->flags & RF_IR_VISIBLE) *lpdest = ((byte *)vid.colormap)[irtable[*lptex]]; @@ -1450,7 +1540,7 @@ void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) lptex += r_affinetridesc.skinwidth; ltfrac &= 0xFFFF; } - } while (--lcount); + } while (lcount--); } pspanpackage ++; @@ -1481,7 +1571,8 @@ void R_RasterizeAliasPolySmooth (void) // set the s, t, and light gradients, which are consistent across the triangle // because being a triangle, things are affine // - R_PolysetCalcGradients (r_affinetridesc.skinwidth); + if( !R_PolysetCalcGradients (r_affinetridesc.skinwidth) ) + return; // // rasterize the polygon // @@ -1496,6 +1587,7 @@ void R_RasterizeAliasPolySmooth (void) d_ptex = (pixel_t*)r_affinetridesc.pskin + (plefttop[2] >> 16) + (plefttop[3] >> 16) * r_affinetridesc.skinwidth; + //#if id386ALIAS #if id386 if ( d_pdrawspans == R_PolysetDrawSpans8_Opaque ) @@ -1520,6 +1612,8 @@ void R_RasterizeAliasPolySmooth (void) if (initialleftheight == 1) { + if( !R_CheckBounds() ) + return; d_pedgespanpackage->pdest = d_pdest; d_pedgespanpackage->pz = d_pz; d_pedgespanpackage->count = d_aspancount; @@ -1531,8 +1625,6 @@ void R_RasterizeAliasPolySmooth (void) // FIXME: need to clamp l, s, t, at both ends? d_pedgespanpackage->light = d_light; d_pedgespanpackage->zi = d_zi; - if( d_pedgespanpackage->ptex - (pixel_t*)r_affinetridesc.pskin < 0 ) - d_pedgespanpackage->ptex = r_affinetridesc.pskin; d_pedgespanpackage++; } @@ -1621,7 +1713,8 @@ void R_RasterizeAliasPolySmooth (void) else #endif { - R_PolysetScanLeftEdge_C(initialleftheight); + if(!R_PolysetScanLeftEdge_C(initialleftheight)) + return; } } @@ -1643,6 +1736,7 @@ void R_RasterizeAliasPolySmooth (void) d_aspancount = plefttop[0] - prighttop[0]; d_ptex = (pixel_t*)r_affinetridesc.pskin + (plefttop[2] >> 16) + (plefttop[3] >> 16) * r_affinetridesc.skinwidth; + d_sfrac = 0; d_tfrac = 0; d_light = plefttop[4]; @@ -1651,6 +1745,10 @@ void R_RasterizeAliasPolySmooth (void) d_pdest = (pixel_t *)d_viewbuffer + ystart * r_screenwidth + plefttop[0]; d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; + if( !R_CheckBounds() ) + return; + + if (height == 1) { d_pedgespanpackage->pdest = d_pdest; @@ -1664,8 +1762,6 @@ void R_RasterizeAliasPolySmooth (void) // FIXME: need to clamp l, s, t, at both ends? d_pedgespanpackage->light = d_light; d_pedgespanpackage->zi = d_zi; - if( d_pedgespanpackage->ptex - (pixel_t*)r_affinetridesc.pskin < 0 ) - d_pedgespanpackage->ptex = r_affinetridesc.pskin; d_pedgespanpackage++; } @@ -1749,7 +1845,8 @@ void R_RasterizeAliasPolySmooth (void) else #endif { - R_PolysetScanLeftEdge_C(height); + if(!R_PolysetScanLeftEdge_C(height)) + return; } } } @@ -1764,6 +1861,11 @@ void R_RasterizeAliasPolySmooth (void) d_countextrastep = ubasestep + 1; originalcount = a_spans[initialrightheight].count; a_spans[initialrightheight].count = -999999; // mark end of the spanpackages + + + if( !R_CheckBounds() ) + return; + (*d_pdrawspans) (a_spans); // scan out the bottom part of the right edge, if it exists @@ -1787,6 +1889,11 @@ void R_RasterizeAliasPolySmooth (void) d_countextrastep = ubasestep + 1; a_spans[initialrightheight + height].count = -999999; + + + if( !R_CheckBounds() ) + return; + // mark end of the spanpackages (*d_pdrawspans) (pstart); } diff --git a/r_surf.c b/r_surf.c index b8c0bde4..40f5c13a 100644 --- a/r_surf.c +++ b/r_surf.c @@ -23,9 +23,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. drawsurf_t r_drawsurf; -int lightleft, sourcesstep, blocksize, sourcetstep; -int lightdelta, lightdeltastep; -int lightright, lightleftstep, lightrightstep, blockdivshift; +uint lightleft, sourcesstep, blocksize, sourcetstep; +uint lightdelta, lightdeltastep; +uint lightright, lightleftstep, lightrightstep, blockdivshift; unsigned blockdivmask; void *prowdestbase; pixel_t *pbasesource; @@ -563,7 +563,8 @@ R_DrawSurfaceBlock8_mip0 */ void R_DrawSurfaceBlock8_mip0 (void) { - int v, i, b, lightstep, lighttemp, light; + int v, i, b; + uint lightstep, lighttemp, light; pixel_t pix, *psource, *prowdest; psource = pbasesource; @@ -618,7 +619,8 @@ R_DrawSurfaceBlock8_mip1 */ void R_DrawSurfaceBlock8_mip1 (void) { - int v, i, b, lightstep, lighttemp, light; + int v, i, b; + uint lightstep, lighttemp, light; pixel_t pix, *psource, *prowdest; psource = pbasesource; @@ -669,7 +671,8 @@ R_DrawSurfaceBlock8_mip2 */ void R_DrawSurfaceBlock8_mip2 (void) { - int v, i, b, lightstep, lighttemp, light; + int v, i, b; + uint lightstep, lighttemp, light; pixel_t pix, *psource, *prowdest; psource = pbasesource; @@ -720,7 +723,8 @@ R_DrawSurfaceBlock8_mip3 */ void R_DrawSurfaceBlock8_mip3 (void) { - int v, i, b, lightstep, lighttemp, light; + int v, i, b; + uint lightstep, lighttemp, light; pixel_t pix, *psource, *prowdest; psource = pbasesource; From 99fa5d0252d1be21d554ea1e57e2764ee0889e99 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 6 Apr 2019 15:55:00 +0700 Subject: [PATCH 075/115] ref_soft: Another bound check implementation (todo: compare) --- r_polyse.c | 172 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 135 insertions(+), 37 deletions(-) diff --git a/r_polyse.c b/r_polyse.c index 1bbafd14..6881f24a 100644 --- a/r_polyse.c +++ b/r_polyse.c @@ -206,55 +206,122 @@ void R_DrawTriangle( void ) } } + +static pixel_t *skinend; + +static inline qboolean R_DrawCheckBounds( pixel_t *lptex ) +{ + pixel_t *skin = r_affinetridesc.pskin; + if( lptex - skin < 0 || lptex - skinend >= 0 ) + return false; + return true; +} + /// TODO: fix this and do not check bounds in shader static inline qboolean R_CheckBounds( void) { - //pixel_t *skin = r_affinetridesc.pskin; - -#if 0 // does not help. Quake 2 Developers, PLEASE FIX UR F***NG CODE!!! +#if 0 + spanpackage_t *pspanpackage = d_pedgespanpackage; + int lcount; + int aspancount = d_aspancount; - int lcount = errorterm >= 0?d_countextrastep:ubasestep; - pixel_t *lptex1, *lptex2, *lptex3, *lptex4; + int lerrorterm = errorterm + erroradjustup; + if (lerrorterm >= 0) + { + aspancount += d_countextrastep; + lerrorterm -= erroradjustdown; + } + else + { + aspancount += ubasestep; + } - lcount+=2; - if( lcount <= 0 ) - lcount = 2; + lcount = pspanpackage->count;//d_aspancount;//max(fabs(ubasestep),fabs(d_countextrastep)); + printf("c %d %d\n", lcount, errorterm ); + if( lcount == 0 ) + lcount = max(fabs(ubasestep),fabs(d_countextrastep)); + if( lcount < 0 ) + return false; + if (lcount) + { + int lsfrac, ltfrac; + byte *lptex; - lptex1 = d_ptex + a_ststepxwhole * lcount + ((a_sstepxfrac * lcount) >> 16) + ((a_tstepxfrac * lcount) >> 16)*r_affinetridesc.skinwidth; - lptex2 = d_ptex + a_ststepxwhole * lcount + ((a_sstepxfrac * lcount) >> 16); - lptex3 = d_ptex + a_ststepxwhole * lcount + ((a_tstepxfrac * lcount) >> 16)*r_affinetridesc.skinwidth; - lptex4 = d_ptex + a_ststepxwhole * lcount; + lptex = pspanpackage->ptex; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; + do + { + if( !R_DrawCheckBounds( lptex ) ) + return false; + + lptex += a_ststepxwhole; + lsfrac += a_sstepxfrac; + lptex += lsfrac >> 16; + lsfrac &= 0xFFFF; + ltfrac += a_tstepxfrac; + if (ltfrac & 0x10000) + { + lptex += r_affinetridesc.skinwidth; + ltfrac &= 0xFFFF; + } + } while (--lcount); + } + return true; +#endif + return true; +} +/// TODO: fix this and do not check bounds in shader +static inline qboolean R_CheckBounds2( spanpackage_t *pspanpackage, int lcount ) +{ + int lsfrac, ltfrac; + byte *lptex; - //if( lptex1 < skin || lptex1 > skin + r_affinetridesc.skinwidth * r_affinetridesc.skinheight ) - // return false; - // if( lptex2 < skin || lptex2 > skin + r_affinetridesc.skinwidth * r_affinetridesc.skinheight ) - // return false; - //if( lptex3 < skin || lptex3 > skin + r_affinetridesc.skinwidth * r_affinetridesc.skinheight ) - // return false; - // if( lptex4 < skin || lptex4 > skin + r_affinetridesc.skinwidth * r_affinetridesc.skinheight ) - // return false; + lptex = pspanpackage->ptex; + lsfrac = pspanpackage->sfrac; + ltfrac = pspanpackage->tfrac; -#endif - //if( d_ptex - skin < 0 || d_ptex - ( skin + r_affinetridesc.skinwidth * r_affinetridesc.skinheight ) >= 0 ) - //return false; + do + { + if( !R_DrawCheckBounds( lptex ) ) + return false; - return true; -} + lptex += a_ststepxwhole; + lsfrac += a_sstepxfrac; + lptex += lsfrac >> 16; + lsfrac &= 0xFFFF; + ltfrac += a_tstepxfrac; + if (ltfrac & 0x10000) + { + lptex += r_affinetridesc.skinwidth; + ltfrac &= 0xFFFF; + } + } while (--lcount); + // try cover all edge cases +/* + if( !R_DrawCheckBounds(lptex) ) + return false; + lcount--; + if( !R_DrawCheckBounds(lptex + a_ststepxwhole * lcount + ((lsfrac * lcount) >> 16)) ) + return false; + if( !R_DrawCheckBounds(lptex + a_ststepxwhole * lcount + ((ltfrac * lcount) >> 16) * r_affinetridesc.skinwidth ) ) + return false; -static pixel_t *skinend; + if( !R_DrawCheckBounds(lptex + ((ltfrac * lcount) >> 16) * r_affinetridesc.skinwidth ) ) + return false; -static inline qboolean R_DrawCheckBounds( pixel_t *lptex ) -{ - pixel_t *skin = r_affinetridesc.pskin; - if( lptex - skin < 0 || lptex - skinend >= 0 ) + if( !R_DrawCheckBounds(lptex + a_ststepxwhole * lcount + ((lsfrac * lcount) >> 16) + ((ltfrac * lcount) >> 16) * r_affinetridesc.skinwidth ) ) return false; +*/ + return true; } + /* =================== R_PolysetScanLeftEdge_C @@ -815,6 +882,10 @@ void R_PolysetDrawSpansBlended( spanpackage_t *pspanpackage) if (lcount) { +#if BOUNDCHECK_MODE == 0 + if( !R_CheckBounds2( pspanpackage, lcount ) ) + return; +#endif lpdest = pspanpackage->pdest; lptex = pspanpackage->ptex; lpz = pspanpackage->pz; @@ -834,8 +905,10 @@ void R_PolysetDrawSpansBlended( spanpackage_t *pspanpackage) return; } #endif +#if BOUNDCHECK_MODE == 1 if( !R_DrawCheckBounds( lptex ) ) return; +#endif pixel_t temp = *lptex;//vid.colormap[*lptex + ( llight & 0xFF00 )]; temp = BLEND_COLOR(temp, vid.color); @@ -907,13 +980,19 @@ void R_PolysetDrawSpansAdditive( spanpackage_t *pspanpackage) ltfrac = pspanpackage->tfrac; llight = pspanpackage->light; lzi = pspanpackage->zi; - +#if BOUNDCHECK_MODE == 0 + if( !R_CheckBounds2( pspanpackage, lcount ) ) + return; +#endif do { + if ((lzi >> 16) >= *lpz) { +#if BOUNDCHECK_MODE == 1 if( !R_DrawCheckBounds( lptex ) ) return; +#endif #if 0 if((int)(lptex - (pixel_t*)r_affinetridesc.pskin) > r_affinetridesc.skinwidth * r_affinetridesc.skinheight || (int)(lptex - (pixel_t*)r_affinetridesc.pskin) < 0 ) { @@ -981,6 +1060,10 @@ void R_PolysetDrawSpansGlow( spanpackage_t *pspanpackage) if (lcount) { +#if BOUNDCHECK_MODE == 0 + if( !R_CheckBounds2( pspanpackage, lcount ) ) + return; +#endif lpdest = pspanpackage->pdest; lptex = pspanpackage->ptex; lpz = pspanpackage->pz; @@ -993,8 +1076,10 @@ void R_PolysetDrawSpansGlow( spanpackage_t *pspanpackage) { //if ((lzi >> 16) >= *lpz) { +#if BOUNDCHECK_MODE == 1 if( !R_DrawCheckBounds( lptex ) ) return; +#endif #if 0 if((int)(lptex - (pixel_t*)r_affinetridesc.pskin) > r_affinetridesc.skinwidth * r_affinetridesc.skinheight || (int)(lptex - (pixel_t*)r_affinetridesc.pskin) < 0 ) { @@ -1062,6 +1147,10 @@ void R_PolysetDrawSpansTextureBlended( spanpackage_t *pspanpackage) if (lcount) { +#if BOUNDCHECK_MODE == 0 + if( !R_CheckBounds2( pspanpackage, lcount ) ) + return; +#endif lpdest = pspanpackage->pdest; lptex = pspanpackage->ptex; lpz = pspanpackage->pz; @@ -1074,8 +1163,10 @@ void R_PolysetDrawSpansTextureBlended( spanpackage_t *pspanpackage) { if ((lzi >> 16) >= *lpz) { +#if BOUNDCHECK_MODE == 1 if( !R_DrawCheckBounds( lptex ) ) return; +#endif #if 0 if((int)(lptex - (pixel_t*)r_affinetridesc.pskin) > r_affinetridesc.skinwidth * r_affinetridesc.skinheight || (int)(lptex - (pixel_t*)r_affinetridesc.pskin) < 0 ) { @@ -1469,6 +1560,7 @@ void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) do { lcount = d_aspancount - pspanpackage->count; + d_ptex + a_ststepxwhole * lcount + ((a_sstepxfrac * lcount) >> 16) + ((a_tstepxfrac * lcount) >> 16)*r_affinetridesc.skinwidth; errorterm += erroradjustup; if (errorterm >= 0) @@ -1489,6 +1581,10 @@ void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) int llight; int lzi; short *lpz; +#if BOUNDCHECK_MODE == 0 + if( !R_CheckBounds2( pspanpackage, lcount ) ) + return; +#endif lpdest = pspanpackage->pdest; lptex = pspanpackage->ptex; @@ -1502,8 +1598,10 @@ void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) { if ((lzi >> 16) >= *lpz) { +#if BOUNDCHECK_MODE == 1 if( !R_DrawCheckBounds( lptex ) ) return; +#endif //PGM /*if(r_newrefdef.rdflags & RDF_IRGOGGLES && RI.currententity->flags & RF_IR_VISIBLE) *lpdest = ((byte *)vid.colormap)[irtable[*lptex]]; @@ -1540,7 +1638,7 @@ void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) lptex += r_affinetridesc.skinwidth; ltfrac &= 0xFFFF; } - } while (lcount--); + } while (--lcount); } pspanpackage ++; @@ -1612,8 +1710,7 @@ void R_RasterizeAliasPolySmooth (void) if (initialleftheight == 1) { - if( !R_CheckBounds() ) - return; + d_pedgespanpackage->pdest = d_pdest; d_pedgespanpackage->pz = d_pz; d_pedgespanpackage->count = d_aspancount; @@ -1625,7 +1722,8 @@ void R_RasterizeAliasPolySmooth (void) // FIXME: need to clamp l, s, t, at both ends? d_pedgespanpackage->light = d_light; d_pedgespanpackage->zi = d_zi; - + if( !R_CheckBounds() ) + return; d_pedgespanpackage++; } else @@ -1745,8 +1843,6 @@ void R_RasterizeAliasPolySmooth (void) d_pdest = (pixel_t *)d_viewbuffer + ystart * r_screenwidth + plefttop[0]; d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0]; - if( !R_CheckBounds() ) - return; if (height == 1) @@ -1763,6 +1859,8 @@ void R_RasterizeAliasPolySmooth (void) d_pedgespanpackage->light = d_light; d_pedgespanpackage->zi = d_zi; + if( !R_CheckBounds() ) + return; d_pedgespanpackage++; } else From 79405c7cc940cb12696c01a058416d5046fa8e10 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sun, 7 Apr 2019 15:52:27 +0700 Subject: [PATCH 076/115] ref_soft: Fix polyset bounds checking --- r_polyse.c | 197 ++++++++++++++++++++--------------------------------- 1 file changed, 72 insertions(+), 125 deletions(-) diff --git a/r_polyse.c b/r_polyse.c index 6881f24a..02c9f5f0 100644 --- a/r_polyse.c +++ b/r_polyse.c @@ -216,78 +216,21 @@ static inline qboolean R_DrawCheckBounds( pixel_t *lptex ) return false; return true; } - -/// TODO: fix this and do not check bounds in shader -static inline qboolean R_CheckBounds( void) -{ #if 0 - spanpackage_t *pspanpackage = d_pedgespanpackage; - int lcount; - int aspancount = d_aspancount; - - int lerrorterm = errorterm + erroradjustup; - if (lerrorterm >= 0) - { - aspancount += d_countextrastep; - lerrorterm -= erroradjustdown; - } - else - { - aspancount += ubasestep; - } - - - lcount = pspanpackage->count;//d_aspancount;//max(fabs(ubasestep),fabs(d_countextrastep)); - printf("c %d %d\n", lcount, errorterm ); - if( lcount == 0 ) - lcount = max(fabs(ubasestep),fabs(d_countextrastep)); - if( lcount < 0 ) - return false; - if (lcount) - { - int lsfrac, ltfrac; - byte *lptex; - - lptex = pspanpackage->ptex; - lsfrac = pspanpackage->sfrac; - ltfrac = pspanpackage->tfrac; - - do - { - if( !R_DrawCheckBounds( lptex ) ) - return false; - - lptex += a_ststepxwhole; - lsfrac += a_sstepxfrac; - lptex += lsfrac >> 16; - lsfrac &= 0xFFFF; - ltfrac += a_tstepxfrac; - if (ltfrac & 0x10000) - { - lptex += r_affinetridesc.skinwidth; - ltfrac &= 0xFFFF; - } - } while (--lcount); - } - return true; -#endif - return true; -} - - -/// TODO: fix this and do not check bounds in shader static inline qboolean R_CheckBounds2( spanpackage_t *pspanpackage, int lcount ) { int lsfrac, ltfrac; - byte *lptex; + pixel_t *lptex, *start, *end; lptex = pspanpackage->ptex; lsfrac = pspanpackage->sfrac; ltfrac = pspanpackage->tfrac; + start = r_affinetridesc.pskin; + end = skinend; do { - if( !R_DrawCheckBounds( lptex ) ) + if( lptex - start < 0 || lptex - end >= 0 ) return false; lptex += a_ststepxwhole; @@ -301,22 +244,43 @@ static inline qboolean R_CheckBounds2( spanpackage_t *pspanpackage, int lcount ) ltfrac &= 0xFFFF; } } while (--lcount); - // try cover all edge cases -/* - if( !R_DrawCheckBounds(lptex) ) - return false; - lcount--; - if( !R_DrawCheckBounds(lptex + a_ststepxwhole * lcount + ((lsfrac * lcount) >> 16)) ) + + // span is linear, so only need to check first and last + + if( lptex - start < 0 || lptex - end >= 0 ) return false; - if( !R_DrawCheckBounds(lptex + a_ststepxwhole * lcount + ((ltfrac * lcount) >> 16) * r_affinetridesc.skinwidth ) ) + + //if( !(--lcount) ) + //return true; + + lptex = lptex + a_ststepxwhole * lcount + ((lsfrac + ( a_sstepxfrac * lcount)) >> 16) + ((ltfrac + (a_tstepxfrac * lcount)) >> 16) * r_affinetridesc.skinwidth; + + if( lptex - start < 0 || lptex - end >= 0 ) return false; - if( !R_DrawCheckBounds(lptex + ((ltfrac * lcount) >> 16) * r_affinetridesc.skinwidth ) ) + + return true; +} +#endif + +static inline qboolean R_PolysetCheckBounds( pixel_t *lptex, int lsfrac, int ltfrac, int lcount ) +{ + pixel_t *start, *end; + start = r_affinetridesc.pskin; + end = skinend; + + // span is linear, so only need to check first and last + if( lptex - start < 0 || lptex - end >= 0 ) return false; - if( !R_DrawCheckBounds(lptex + a_ststepxwhole * lcount + ((lsfrac * lcount) >> 16) + ((ltfrac * lcount) >> 16) * r_affinetridesc.skinwidth ) ) + if( !(--lcount) ) + return true; + + lptex = lptex + a_ststepxwhole * lcount + ((lsfrac + ( a_sstepxfrac * lcount)) >> 16) + ((ltfrac + (a_tstepxfrac * lcount)) >> 16) * r_affinetridesc.skinwidth; + + if( lptex - start < 0 || lptex - end >= 0 ) return false; -*/ + return true; } @@ -343,10 +307,6 @@ qboolean R_PolysetScanLeftEdge_C(int height) d_pedgespanpackage->light = d_light; d_pedgespanpackage->zi = d_zi; - - if( !R_CheckBounds() ) - return false; - d_pedgespanpackage++; errorterm += erroradjustup; @@ -805,14 +765,14 @@ qboolean R_PolysetCalcGradients (int skinwidth) r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv); - if( r_zistepx > INT_MAX / 2 ) + /*if( r_zistepx > INT_MAX / 2 ) return false; if( r_zistepx < INT_MIN / 2 ) return false; if( r_zistepy > INT_MAX / 2 ) return false; if( r_zistepy < INT_MIN / 2 ) - return false; + return false;*/ //#if id386ALIAS @@ -832,14 +792,14 @@ qboolean R_PolysetCalcGradients (int skinwidth) //#endif // do not allow big steps to make 512 byte extra bounds enough (still f**ng not) - if( r_sstepx <= -65535*8 ) + /*if( r_sstepx <= -65535*8 ) return false; if( r_tstepx <= -65535*8) return false; if( r_sstepx >= 65535*8 ) return false; if( r_tstepx >= 65535*8 ) - return false; + return false;*/ a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16); @@ -882,10 +842,6 @@ void R_PolysetDrawSpansBlended( spanpackage_t *pspanpackage) if (lcount) { -#if BOUNDCHECK_MODE == 0 - if( !R_CheckBounds2( pspanpackage, lcount ) ) - return; -#endif lpdest = pspanpackage->pdest; lptex = pspanpackage->ptex; lpz = pspanpackage->pz; @@ -893,7 +849,11 @@ void R_PolysetDrawSpansBlended( spanpackage_t *pspanpackage) ltfrac = pspanpackage->tfrac; llight = pspanpackage->light; lzi = pspanpackage->zi; - + pspanpackage++; +#if BOUNDCHECK_MODE == 0 + if( !R_PolysetCheckBounds( lptex, lsfrac, ltfrac, lcount ) ) + continue; +#endif do { if ((lzi >> 16) >= *lpz) @@ -935,8 +895,7 @@ void R_PolysetDrawSpansBlended( spanpackage_t *pspanpackage) } } while (--lcount); } - - pspanpackage++; + else pspanpackage++; } while (pspanpackage->count != -999999); } @@ -980,9 +939,10 @@ void R_PolysetDrawSpansAdditive( spanpackage_t *pspanpackage) ltfrac = pspanpackage->tfrac; llight = pspanpackage->light; lzi = pspanpackage->zi; + pspanpackage++; #if BOUNDCHECK_MODE == 0 - if( !R_CheckBounds2( pspanpackage, lcount ) ) - return; + if( !R_PolysetCheckBounds( lptex, lsfrac, ltfrac, lcount ) ) + continue; #endif do { @@ -1022,8 +982,7 @@ void R_PolysetDrawSpansAdditive( spanpackage_t *pspanpackage) } } while (--lcount); } - - pspanpackage++; + else pspanpackage++; } while (pspanpackage->count != -999999); } @@ -1060,10 +1019,6 @@ void R_PolysetDrawSpansGlow( spanpackage_t *pspanpackage) if (lcount) { -#if BOUNDCHECK_MODE == 0 - if( !R_CheckBounds2( pspanpackage, lcount ) ) - return; -#endif lpdest = pspanpackage->pdest; lptex = pspanpackage->ptex; lpz = pspanpackage->pz; @@ -1071,7 +1026,11 @@ void R_PolysetDrawSpansGlow( spanpackage_t *pspanpackage) ltfrac = pspanpackage->tfrac; llight = pspanpackage->light; lzi = pspanpackage->zi; - + pspanpackage++; +#if BOUNDCHECK_MODE == 0 + if( !R_PolysetCheckBounds( lptex, lsfrac, ltfrac, lcount ) ) + continue; +#endif do { //if ((lzi >> 16) >= *lpz) @@ -1109,8 +1068,8 @@ void R_PolysetDrawSpansGlow( spanpackage_t *pspanpackage) } } while (--lcount); } - - pspanpackage++; + else + pspanpackage++; } while (pspanpackage->count != -999999); } @@ -1147,10 +1106,7 @@ void R_PolysetDrawSpansTextureBlended( spanpackage_t *pspanpackage) if (lcount) { -#if BOUNDCHECK_MODE == 0 - if( !R_CheckBounds2( pspanpackage, lcount ) ) - return; -#endif + lpdest = pspanpackage->pdest; lptex = pspanpackage->ptex; lpz = pspanpackage->pz; @@ -1158,7 +1114,11 @@ void R_PolysetDrawSpansTextureBlended( spanpackage_t *pspanpackage) ltfrac = pspanpackage->tfrac; llight = pspanpackage->light; lzi = pspanpackage->zi; - + pspanpackage++; +#if BOUNDCHECK_MODE == 0 + if( !R_PolysetCheckBounds( lptex, lsfrac, ltfrac, lcount ) ) + continue; +#endif do { if ((lzi >> 16) >= *lpz) @@ -1200,8 +1160,8 @@ void R_PolysetDrawSpansTextureBlended( spanpackage_t *pspanpackage) } } while (--lcount); } - - pspanpackage++; + else + pspanpackage++; } while (pspanpackage->count != -999999); } @@ -1581,10 +1541,7 @@ void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) int llight; int lzi; short *lpz; -#if BOUNDCHECK_MODE == 0 - if( !R_CheckBounds2( pspanpackage, lcount ) ) - return; -#endif + lpdest = pspanpackage->pdest; lptex = pspanpackage->ptex; @@ -1593,6 +1550,11 @@ void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) ltfrac = pspanpackage->tfrac; llight = pspanpackage->light; lzi = pspanpackage->zi; + pspanpackage ++; +#if BOUNDCHECK_MODE == 0 + if( !R_PolysetCheckBounds( lptex, lsfrac, ltfrac, lcount ) ) + continue; +#endif do { @@ -1640,8 +1602,7 @@ void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) } } while (--lcount); } - - pspanpackage ++; + else pspanpackage++; } while (pspanpackage->count != -999999); } #endif @@ -1722,8 +1683,6 @@ void R_RasterizeAliasPolySmooth (void) // FIXME: need to clamp l, s, t, at both ends? d_pedgespanpackage->light = d_light; d_pedgespanpackage->zi = d_zi; - if( !R_CheckBounds() ) - return; d_pedgespanpackage++; } else @@ -1858,9 +1817,6 @@ void R_RasterizeAliasPolySmooth (void) // FIXME: need to clamp l, s, t, at both ends? d_pedgespanpackage->light = d_light; d_pedgespanpackage->zi = d_zi; - - if( !R_CheckBounds() ) - return; d_pedgespanpackage++; } else @@ -1960,10 +1916,6 @@ void R_RasterizeAliasPolySmooth (void) originalcount = a_spans[initialrightheight].count; a_spans[initialrightheight].count = -999999; // mark end of the spanpackages - - if( !R_CheckBounds() ) - return; - (*d_pdrawspans) (a_spans); // scan out the bottom part of the right edge, if it exists @@ -1987,12 +1939,7 @@ void R_RasterizeAliasPolySmooth (void) d_countextrastep = ubasestep + 1; a_spans[initialrightheight + height].count = -999999; - - - if( !R_CheckBounds() ) - return; - - // mark end of the spanpackages + // mark end of the spanpackages (*d_pdrawspans) (pstart); } } From 320a3b0834bd05e77e4f659630b952d811779ea6 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sun, 7 Apr 2019 22:10:41 +0700 Subject: [PATCH 077/115] ref_soft: Fix cache flush on reconnect, fix division by zero in decals --- r_local.h | 3 ++- r_main.c | 6 +++--- r_misc.c | 2 +- r_surf.c | 12 ++++++++---- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/r_local.h b/r_local.h index 485a0a04..346bcce2 100644 --- a/r_local.h +++ b/r_local.h @@ -293,6 +293,7 @@ typedef struct vec3_t modelorg; // relative to viewpoint qboolean fCustomSkybox; + char mapname[MAX_STRING]; } gl_globals_t; typedef struct @@ -1247,7 +1248,7 @@ void R_ScanEdges (void); // // r_surf.c // -void D_FlushCaches( qboolean newmap ); +void D_FlushCaches( void ); // // r_draw.c diff --git a/r_main.c b/r_main.c index 7601f76f..a37797e7 100644 --- a/r_main.c +++ b/r_main.c @@ -1671,7 +1671,7 @@ void R_BeginFrame( qboolean clearScene ) // glConfig.softwareGammaUpdate = true; // GL_RebuildLightmaps(); // glConfig.softwareGammaUpdate = false; - D_FlushCaches( false ); + D_FlushCaches( ); // next frame will be restored gamma SetBits( vid_brightness->flags, FCVAR_CHANGED ); @@ -1682,7 +1682,7 @@ void R_BeginFrame( qboolean clearScene ) gEngfuncs.BuildGammaTable( vid_gamma->value, vid_brightness->value ); //glConfig.softwareGammaUpdate = true; // GL_RebuildLightmaps(); - D_FlushCaches( false ); + D_FlushCaches( ); //glConfig.softwareGammaUpdate = false; // next frame will be restored gamma ClearBits( vid_brightness->flags, FCVAR_CHANGED ); @@ -1833,7 +1833,7 @@ void R_NewMap (void) R_ClearDecals(); // clear all level decals R_StudioResetPlayerModels(); - D_FlushCaches( true ); + D_FlushCaches(); r_cnumsurfs = sw_maxsurfs->value; diff --git a/r_misc.c b/r_misc.c index 7bbb66e2..7d02bb48 100644 --- a/r_misc.c +++ b/r_misc.c @@ -318,7 +318,7 @@ void R_SetupFrameQ (void) if (r_fullbright->flags & FCVAR_CHANGED) { r_fullbright->flags &= ~FCVAR_CHANGED; - D_FlushCaches( false ); // so all lighting changes + D_FlushCaches( ); // so all lighting changes } //tr.framecount++; diff --git a/r_surf.c b/r_surf.c index 40f5c13a..9a18a81e 100644 --- a/r_surf.c +++ b/r_surf.c @@ -806,7 +806,7 @@ void R_InitCaches (void) sc_size = size; if( sc_base ) { - D_FlushCaches( false ); + D_FlushCaches( ); Mem_Free( sc_base ); } sc_base = (surfcache_t *)Mem_Calloc(r_temppool,size); @@ -823,10 +823,12 @@ void R_InitCaches (void) D_FlushCaches ================== */ -void D_FlushCaches( qboolean newmap ) +void D_FlushCaches( void ) { surfcache_t *c; - + model_t *world = WORLDMODEL; + qboolean newmap = !world || !Q_strcmp( tr.mapname, WORLDMODEL->name ); + // if newmap, surfaces already freed if( !newmap ) { @@ -836,6 +838,8 @@ void D_FlushCaches( qboolean newmap ) *c->owner = NULL; } } + else + Q_strncpy( tr.mapname, WORLDMODEL->name, MAX_STRING ); sc_rover = sc_base; sc_base->next = NULL; @@ -1040,7 +1044,7 @@ void R_DrawSurfaceDecals() if( t2 > tex->height ) t2 = tex->height; - if( !tex->pixels[0] || s1 >= s2 || t1 >= t2 ) + if( !tex->pixels[0] || s1 >= s2 || t1 >= t2 || !w ) continue; if( tex->alpha_pixels ) From 5140bb8d7f5deeabe2149ddc3cb23f1f06e4684a Mon Sep 17 00:00:00 2001 From: mittorn Date: Sun, 7 Apr 2019 22:29:48 +0700 Subject: [PATCH 078/115] ref_soft: Use Q_memprint to report cache size --- r_surf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/r_surf.c b/r_surf.c index 9a18a81e..db6aafa2 100644 --- a/r_surf.c +++ b/r_surf.c @@ -801,7 +801,7 @@ void R_InitCaches (void) // round up to page size size = (size + 8191) & ~8191; - gEngfuncs.Con_Printf ("%ik surface cache\n", size/1024); + gEngfuncs.Con_Printf ("%s surface cache\n", Q_memprint(size)); sc_size = size; if( sc_base ) From 4dae13d7bc3f6bf51e55c7e3c9bdade8b0c82723 Mon Sep 17 00:00:00 2001 From: mittorn Date: Mon, 8 Apr 2019 05:09:02 +0700 Subject: [PATCH 079/115] ref_soft: Add GAME_EXPORT to exports --- r_beams.c | 6 ++-- r_context.c | 84 ++++++++++++++++++++++++++--------------------------- r_decals.c | 12 ++++---- r_draw.c | 14 ++++----- r_image.c | 20 ++++++------- r_light.c | 6 ++-- r_local.h | 2 +- r_main.c | 26 ++++++++--------- r_part.c | 6 ++-- r_sprite.c | 2 +- r_studio.c | 10 +++---- r_triapi.c | 26 ++++++++--------- 12 files changed, 107 insertions(+), 107 deletions(-) diff --git a/r_beams.c b/r_beams.c index 759b751a..166b71a0 100644 --- a/r_beams.c +++ b/r_beams.c @@ -116,7 +116,7 @@ R_BeamCull Cull the beam by bbox ============== */ -qboolean R_BeamCull( const vec3_t start, const vec3_t end, qboolean pvsOnly ) +qboolean GAME_EXPORT R_BeamCull( const vec3_t start, const vec3_t end, qboolean pvsOnly ) { vec3_t mins, maxs; int i; @@ -162,7 +162,7 @@ CL_AddCustomBeam Add the beam that encoded as custom entity ================ */ -void CL_AddCustomBeam( cl_entity_t *pEnvBeam ) +void GAME_EXPORT CL_AddCustomBeam( cl_entity_t *pEnvBeam ) { if( tr.draw_list->num_beam_entities >= MAX_VISIBLE_PACKET ) { @@ -1269,7 +1269,7 @@ CL_DrawBeams draw beam loop ============== */ -void CL_DrawBeams( int fTrans, BEAM *active_beams ) +void GAME_EXPORT CL_DrawBeams( int fTrans, BEAM *active_beams ) { BEAM *pBeam; int i, flags; diff --git a/r_context.c b/r_context.c index 69855083..101d093a 100644 --- a/r_context.c +++ b/r_context.c @@ -27,17 +27,17 @@ cvar_t *r_norefresh; cvar_t *vid_gamma; cvar_t *vid_brightness; viddef_t vid; -static void R_ClearScreen( void ) +static void GAME_EXPORT R_ClearScreen( void ) { } -static qboolean IsNormalPass( void ) +static qboolean GAME_EXPORT IsNormalPass( void ) { return RP_NORMALPASS(); } -static void R_IncrementSpeedsCounter( int type ) +static void GAME_EXPORT R_IncrementSpeedsCounter( int type ) { switch( type ) { @@ -49,7 +49,7 @@ static void R_IncrementSpeedsCounter( int type ) } } -static const byte *R_GetTextureOriginalBuffer( unsigned int idx ) +static const byte * GAME_EXPORT R_GetTextureOriginalBuffer( unsigned int idx ) { /*gl_texture_t *glt = R_GetTexture( idx ); @@ -59,7 +59,7 @@ static const byte *R_GetTextureOriginalBuffer( unsigned int idx ) return NULL; } -static int R_GetBuiltinTexture( enum ref_shared_texture_e type ) +static int GAME_EXPORT R_GetBuiltinTexture( enum ref_shared_texture_e type ) { switch( type ) { @@ -74,7 +74,7 @@ static int R_GetBuiltinTexture( enum ref_shared_texture_e type ) return 0; } -static void R_FreeSharedTexture( enum ref_shared_texture_e type ) +static void GAME_EXPORT R_FreeSharedTexture( enum ref_shared_texture_e type ) { int num = 0; @@ -104,7 +104,7 @@ CL_FillRGBA ============= */ -static void CL_FillRGBA( float _x, float _y, float _w, float _h, int r, int g, int b, int a ) +static void GAME_EXPORT CL_FillRGBA( float _x, float _y, float _w, float _h, int r, int g, int b, int a ) { vid.rendermode = kRenderTransAdd; _TriColor4ub(r,g,b,a); @@ -125,7 +125,7 @@ static void GAME_EXPORT CL_FillRGBABlend( float _x, float _y, float _w, float _h } -qboolean Mod_ProcessRenderData( model_t *mod, qboolean create, const byte *buf ) +qboolean GAME_EXPORT Mod_ProcessRenderData( model_t *mod, qboolean create, const byte *buf ) { qboolean loaded = true; @@ -161,7 +161,7 @@ qboolean Mod_ProcessRenderData( model_t *mod, qboolean create, const byte *buf ) return loaded; } -static int GL_RenderGetParm( int parm, int arg ) +static int GAME_EXPORT GL_RenderGetParm( int parm, int arg ) { image_t *glt; @@ -223,7 +223,7 @@ static int GL_RenderGetParm( int parm, int arg ) return 0; } -static void R_GetDetailScaleForTexture( int texture, float *xScale, float *yScale ) +static void GAME_EXPORT R_GetDetailScaleForTexture( int texture, float *xScale, float *yScale ) { image_t *glt = R_GetTexture( texture ); @@ -231,7 +231,7 @@ static void R_GetDetailScaleForTexture( int texture, float *xScale, float *yScal if( yScale ) *yScale = glt->yscale; } -static void R_GetExtraParmsForTexture( int texture, byte *red, byte *green, byte *blue, byte *density ) +static void GAME_EXPORT R_GetExtraParmsForTexture( int texture, byte *red, byte *green, byte *blue, byte *density ) { image_t *glt = R_GetTexture( texture ); @@ -242,7 +242,7 @@ static void R_GetExtraParmsForTexture( int texture, byte *red, byte *green, byte } -static void R_SetCurrentEntity( cl_entity_t *ent ) +static void GAME_EXPORT R_SetCurrentEntity( cl_entity_t *ent ) { RI.currententity = ent; @@ -253,22 +253,22 @@ static void R_SetCurrentEntity( cl_entity_t *ent ) } } -static void R_SetCurrentModel( model_t *mod ) +static void GAME_EXPORT R_SetCurrentModel( model_t *mod ) { RI.currentmodel = mod; } -static float R_GetFrameTime( void ) +static float GAME_EXPORT R_GetFrameTime( void ) { return tr.frametime; } -static const char *GL_TextureName( unsigned int texnum ) +static const char * GAME_EXPORT GL_TextureName( unsigned int texnum ) { return "";//return R_GetTexture( texnum )->name; } -const byte *GL_TextureData( unsigned int texnum ) +const byte * GAME_EXPORT GL_TextureData( unsigned int texnum ) { // rgbdata_t *pic = R_GetTexture( texnum )->original; @@ -316,72 +316,72 @@ void Mod_UnloadTextures( model_t *mod ) } } -void R_ProcessEntData( qboolean allocate ) +void GAME_EXPORT R_ProcessEntData( qboolean allocate ) { } // stubs -void GL_SetTexCoordArrayMode() +void GAME_EXPORT GL_SetTexCoordArrayMode() { } -void GL_OnContextCreated() +void GAME_EXPORT GL_OnContextCreated() { //R_InitBlit(); } -void GL_InitExtensions() +void GAME_EXPORT GL_InitExtensions() { } -void GL_ClearExtensions() +void GAME_EXPORT GL_ClearExtensions() { } -void GL_BackendStartFrame() +void GAME_EXPORT GL_BackendStartFrame() { } -void GL_BackendEndFrame() +void GAME_EXPORT GL_BackendEndFrame() { } -void GL_SetRenderMode(int mode) +void GAME_EXPORT GL_SetRenderMode(int mode) { vid.rendermode = mode; /// TODO: table shading/blending??? /// maybe, setup block drawing function pointers here } -void R_ShowTextures() +void GAME_EXPORT R_ShowTextures() { // textures undone too } -void R_ShowTree() +void GAME_EXPORT R_ShowTree() { // do we really need this here??? } -void R_SetupSky(const char *skyboxname) +void GAME_EXPORT R_SetupSky(const char *skyboxname) { } -qboolean VID_ScreenShot(const char *filename, int shot_type) +qboolean GAME_EXPORT VID_ScreenShot(const char *filename, int shot_type) { } -qboolean VID_CubemapShot(const char *base, uint size, const float *vieworg, qboolean skyshot) +qboolean GAME_EXPORT VID_CubemapShot(const char *base, uint size, const float *vieworg, qboolean skyshot) { // cubemaps? in my softrender??? } @@ -391,67 +391,67 @@ void R_InitSkyClouds(mip_t *mt, texture_t *tx, qboolean custom_palette) } -void GL_SubdivideSurface(msurface_t *fa) +void GAME_EXPORT GL_SubdivideSurface(msurface_t *fa) { } -void DrawSingleDecal(decal_t *pDecal, msurface_t *fa) +void GAME_EXPORT DrawSingleDecal(decal_t *pDecal, msurface_t *fa) { } -void GL_SelectTexture(int texture) +void GAME_EXPORT GL_SelectTexture(int texture) { } -void GL_LoadTexMatrixExt(const float *glmatrix) +void GAME_EXPORT GL_LoadTexMatrixExt(const float *glmatrix) { } -void GL_LoadIdentityTexMatrix() +void GAME_EXPORT GL_LoadIdentityTexMatrix() { } -void GL_CleanUpTextureUnits(int last) +void GAME_EXPORT GL_CleanUpTextureUnits(int last) { } -void GL_TexGen(unsigned int coord, unsigned int mode) +void GAME_EXPORT GL_TexGen(unsigned int coord, unsigned int mode) { } -void GL_TextureTarget(uint target) +void GAME_EXPORT GL_TextureTarget(uint target) { } -void GL_BuildLightmaps() +void GAME_EXPORT GL_BuildLightmaps() { CL_RunLightStyles(); } -void Mod_SetOrthoBounds(const float *mins, const float *maxs) +void GAME_EXPORT Mod_SetOrthoBounds(const float *mins, const float *maxs) { } -qboolean R_SpeedsMessage(char *out, size_t size) +qboolean GAME_EXPORT R_SpeedsMessage(char *out, size_t size) { return false; } -byte *Mod_GetCurrentVis() +byte *GAME_EXPORT Mod_GetCurrentVis() { return NULL; } -void GL_SetupAttributes( int safegl ) +void GAME_EXPORT GL_SetupAttributes( int safegl ) { gEngfuncs.Con_Reportf( "Creating an extended GL context for debug...\n" ); gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_FLAGS, REF_GL_CONTEXT_DEBUG_FLAG ); diff --git a/r_decals.c b/r_decals.c index 27716742..4087e2f2 100644 --- a/r_decals.c +++ b/r_decals.c @@ -759,7 +759,7 @@ static void R_DecalNode( model_t *model, mnode_t *node, decalinfo_t *decalinfo ) } // Shoots a decal onto the surface of the BSP. position is the center of the decal in world coords -void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale ) +void GAME_EXPORT R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos, int flags, float scale ) { decalinfo_t decalInfo; cl_entity_t *ent = NULL; @@ -852,7 +852,7 @@ void R_DecalShoot( int textureIndex, int entityIndex, int modelIndex, vec3_t pos // Build the vertex list for a decal on a surface and clip it to the surface. // This is a template so it can work on world surfaces and dynamic displacement // triangles the same way. -float *R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, int texture, int *outCount ) +float * GAME_EXPORT R_DecalSetupVerts( decal_t *pDecal, msurface_t *surf, int texture, int *outCount ) { glpoly_t *p = pDecal->polys; int i, count; @@ -1168,7 +1168,7 @@ static int DecalDepthCompare( const void *a, const void *b ) // Input : *pList - // Output : int //----------------------------------------------------------------------------- -int R_CreateDecalList( decallist_t *pList ) +int GAME_EXPORT R_CreateDecalList( decallist_t *pList ) { int total = 0; int i, depth; @@ -1226,7 +1226,7 @@ R_DecalRemoveAll remove all decals with specified texture =============== */ -void R_DecalRemoveAll( int textureIndex ) +void GAME_EXPORT R_DecalRemoveAll( int textureIndex ) { decal_t *pdecal; int i; @@ -1254,7 +1254,7 @@ R_EntityRemoveDecals remove all decals from specified entity =============== */ -void R_EntityRemoveDecals( model_t *mod ) +void GAME_EXPORT R_EntityRemoveDecals( model_t *mod ) { msurface_t *psurf; decal_t *p; @@ -1279,7 +1279,7 @@ remove all decals from anything used for full decals restart =============== */ -void R_ClearAllDecals( void ) +void GAME_EXPORT R_ClearAllDecals( void ) { decal_t *pdecal; int i; diff --git a/r_draw.c b/r_draw.c index 06117f3b..ef5adea3 100644 --- a/r_draw.c +++ b/r_draw.c @@ -37,7 +37,7 @@ same as GetImageParms but used for sprite models ============= */ -void R_GetSpriteParms( int *frameWidth, int *frameHeight, int *numFrames, int currentFrame, const model_t *pSprite ) +void GAME_EXPORT R_GetSpriteParms( int *frameWidth, int *frameHeight, int *numFrames, int currentFrame, const model_t *pSprite ) { mspriteframe_t *pFrame; @@ -49,7 +49,7 @@ void R_GetSpriteParms( int *frameWidth, int *frameHeight, int *numFrames, int cu if( numFrames ) *numFrames = pSprite->numframes; } -int R_GetSpriteTexture( const model_t *m_pSpriteModel, int frame ) +int GAME_EXPORT R_GetSpriteTexture( const model_t *m_pSpriteModel, int frame ) { if( !m_pSpriteModel || m_pSpriteModel->type != mod_sprite || !m_pSpriteModel->cache.data ) return 0; @@ -188,7 +188,7 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, R_DrawStretchPic ============= */ -void R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum ) +void GAME_EXPORT R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum ) { image_t *pic = R_GetTexture(texnum); // GL_Bind( XASH_TEXTURE0, texnum ); @@ -285,7 +285,7 @@ This repeats a 64*64 tile graphic to fill the screen around a sized down refresh window. ============= */ -void R_DrawTileClear( int texnum, int x, int y, int w, int h ) +void GAME_EXPORT R_DrawTileClear( int texnum, int x, int y, int w, int h ) { int tw, th, x2, i, j; image_t *pic; @@ -331,7 +331,7 @@ void R_DrawTileClear( int texnum, int x, int y, int w, int h ) R_DrawStretchRaw ============= */ -void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean dirty ) +void GAME_EXPORT R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean dirty ) { byte *raw = NULL; image_t *tex; @@ -351,7 +351,7 @@ void R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, c R_UploadStretchRaw ============= */ -void R_UploadStretchRaw( int texture, int cols, int rows, int width, int height, const byte *data ) +void GAME_EXPORT R_UploadStretchRaw( int texture, int cols, int rows, int width, int height, const byte *data ) { byte *raw = NULL; image_t *tex; @@ -368,7 +368,7 @@ void R_UploadStretchRaw( int texture, int cols, int rows, int width, int height, R_Set2DMode =============== */ -void R_Set2DMode( qboolean enable ) +void GAME_EXPORT R_Set2DMode( qboolean enable ) { vid.color = COLOR_WHITE; vid.is2d = enable; diff --git a/r_image.c b/r_image.c index 462ec3b5..1744346c 100644 --- a/r_image.c +++ b/r_image.c @@ -40,7 +40,7 @@ image_t *R_GetTexture( unsigned int texnum ) GL_Bind ================= */ -void GL_Bind( int tmu, unsigned int texnum ) +void GAME_EXPORT GL_Bind( int tmu, unsigned int texnum ) { image_t *image; @@ -929,7 +929,7 @@ GL_UpdateTexSize recalc image room ================ */ -void GL_UpdateTexSize( int texnum, int width, int height, int depth ) +void GAME_EXPORT GL_UpdateTexSize( int texnum, int width, int height, int depth ) { int i, j, texsize; int numSides; @@ -960,7 +960,7 @@ void GL_UpdateTexSize( int texnum, int width, int height, int depth ) GL_LoadTexture ================ */ -int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags ) +int GAME_EXPORT GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags ) { image_t *tex; rgbdata_t *pic; @@ -1008,7 +1008,7 @@ int GL_LoadTexture( const char *name, const byte *buf, size_t size, int flags ) GL_LoadTextureArray ================ */ -int GL_LoadTextureArray( const char **names, int flags ) +int GAME_EXPORT GL_LoadTextureArray( const char **names, int flags ) { return 0; } @@ -1018,7 +1018,7 @@ int GL_LoadTextureArray( const char **names, int flags ) GL_LoadTextureFromBuffer ================ */ -int GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update ) +int GAME_EXPORT GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags, qboolean update ) { image_t *tex; @@ -1062,7 +1062,7 @@ GL_CreateTexture creates texture from buffer ================ */ -int GL_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags ) +int GAME_EXPORT GL_CreateTexture( const char *name, int width, int height, const void *buffer, texFlags_t flags ) { int datasize = 1; rgbdata_t r_empty; @@ -1104,7 +1104,7 @@ GL_CreateTextureArray creates texture array from buffer ================ */ -int GL_CreateTextureArray( const char *name, int width, int height, int depth, const void *buffer, texFlags_t flags ) +int GAME_EXPORT GL_CreateTextureArray( const char *name, int width, int height, int depth, const void *buffer, texFlags_t flags ) { return 0; } @@ -1114,7 +1114,7 @@ int GL_CreateTextureArray( const char *name, int width, int height, int depth, c GL_FindTexture ================ */ -int GL_FindTexture( const char *name ) +int GAME_EXPORT GL_FindTexture( const char *name ) { image_t *tex; @@ -1133,7 +1133,7 @@ int GL_FindTexture( const char *name ) GL_FreeTexture ================ */ -void GL_FreeTexture( unsigned int texnum ) +void GAME_EXPORT GL_FreeTexture( unsigned int texnum ) { // number 0 it's already freed if( texnum <= 0 ) @@ -1147,7 +1147,7 @@ void GL_FreeTexture( unsigned int texnum ) GL_ProcessTexture ================ */ -void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor ) +void GAME_EXPORT GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor ) { image_t *image; rgbdata_t *pic; diff --git a/r_light.c b/r_light.c index 0e4c2077..8f292e29 100644 --- a/r_light.c +++ b/r_light.c @@ -35,7 +35,7 @@ CL_RunLightStyles ================== */ -void CL_RunLightStyles( void ) +void GAME_EXPORT CL_RunLightStyles( void ) { int i, k, flight, clight; float l, lerpfrac, backlerp; @@ -468,7 +468,7 @@ R_LightVec check bspmodels to get light from ================= */ -colorVec R_LightVec( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t lvec ) +colorVec GAME_EXPORT R_LightVec( const vec3_t start, const vec3_t end, vec3_t lspot, vec3_t lvec ) { colorVec light = R_LightVecInternal( start, end, lspot, lvec ); @@ -491,7 +491,7 @@ R_LightPoint light from floor ================= */ -colorVec R_LightPoint( const vec3_t p0 ) +colorVec GAME_EXPORT R_LightPoint( const vec3_t p0 ) { vec3_t p1; diff --git a/r_local.h b/r_local.h index 346bcce2..ad3bf50a 100644 --- a/r_local.h +++ b/r_local.h @@ -576,7 +576,7 @@ void R_DrawClouds( void ); void EmitWaterPolys( msurface_t *warp, qboolean reverse ); #endif -void R_InitSkyClouds( struct mip_s *mt, struct texture_s *tx, qboolean custom_palette ); +void GAME_EXPORT R_InitSkyClouds( struct mip_s *mt, struct texture_s *tx, qboolean custom_palette ); // // gl_vgui.c // diff --git a/r_main.c b/r_main.c index a37797e7..c50538be 100644 --- a/r_main.c +++ b/r_main.c @@ -160,7 +160,7 @@ int R_GetEntityRenderMode( cl_entity_t *ent ) } #endif -void R_AllowFog( qboolean allowed ) +void GAME_EXPORT R_AllowFog( qboolean allowed ) { } @@ -289,7 +289,7 @@ R_ScreenToWorld Convert a given point from screen into world space =============== */ -void R_ScreenToWorld( const vec3_t screen, vec3_t point ) +void GAME_EXPORT R_ScreenToWorld( const vec3_t screen, vec3_t point ) { matrix4x4 screenToWorld; float w; @@ -313,7 +313,7 @@ void R_ScreenToWorld( const vec3_t screen, vec3_t point ) R_PushScene =============== */ -void R_PushScene( void ) +void GAME_EXPORT R_PushScene( void ) { if( ++tr.draw_stack_pos >= MAX_DRAW_STACK ) gEngfuncs.Host_Error( "draw stack overflow\n" ); @@ -326,7 +326,7 @@ void R_PushScene( void ) R_PopScene =============== */ -void R_PopScene( void ) +void GAME_EXPORT R_PopScene( void ) { if( --tr.draw_stack_pos < 0 ) gEngfuncs.Host_Error( "draw stack underflow\n" ); @@ -338,7 +338,7 @@ void R_PopScene( void ) R_ClearScene =============== */ -void R_ClearScene( void ) +void GAME_EXPORT R_ClearScene( void ) { tr.draw_list->num_solid_entities = 0; tr.draw_list->num_trans_entities = 0; @@ -356,7 +356,7 @@ void R_ClearScene( void ) R_AddEntity =============== */ -qboolean R_AddEntity( struct cl_entity_s *clent, int type ) +qboolean GAME_EXPORT R_AddEntity( struct cl_entity_s *clent, int type ) { if( !r_drawentities->value ) return false; // not allow to drawing @@ -1581,7 +1581,7 @@ R_RenderScene R_SetupRefParams must be called right before ================ */ -void R_RenderScene( void ) +void GAME_EXPORT R_RenderScene( void ) { if( !WORLDMODEL && RI.drawWorld ) gEngfuncs.Host_Error( "R_RenderView: NULL worldmodel\n" ); @@ -1662,7 +1662,7 @@ qboolean R_DoResetGamma( void ) R_BeginFrame =============== */ -void R_BeginFrame( qboolean clearScene ) +void GAME_EXPORT R_BeginFrame( qboolean clearScene ) { if( R_DoResetGamma( )) @@ -1738,7 +1738,7 @@ void R_SetupRefParams( const ref_viewpass_t *rvp ) R_RenderFrame =============== */ -int R_RenderFrame( const ref_viewpass_t *rvp ) +int GAME_EXPORT R_RenderFrame( const ref_viewpass_t *rvp ) { if( r_norefresh->value ) return 1; @@ -1779,7 +1779,7 @@ int R_RenderFrame( const ref_viewpass_t *rvp ) R_EndFrame =============== */ -void R_EndFrame( void ) +void GAME_EXPORT R_EndFrame( void ) { // flush any remaining 2D bits R_Set2DMode( false ); @@ -1820,7 +1820,7 @@ void R_DrawCubemapView( const vec3_t origin, const vec3_t angles, int size ) R_NewMap =============== */ -void R_NewMap (void) +void GAME_EXPORT R_NewMap (void) { int i; r_viewcluster = -1; @@ -1894,7 +1894,7 @@ void R_InitTurb (void) -qboolean R_Init() +qboolean GAME_EXPORT R_Init() { gl_emboss_scale = gEngfuncs.Cvar_Get( "gl_emboss_scale", "0", FCVAR_ARCHIVE|FCVAR_LATCH, "fake bumpmapping scale" ); vid_gamma = gEngfuncs.pfnGetCvarPointer( "gamma", 0 ); @@ -1968,7 +1968,7 @@ qboolean R_Init() return true; } -void R_Shutdown() +void GAME_EXPORT R_Shutdown() { R_ShutdownImages(); gEngfuncs.R_Free_Video(); diff --git a/r_part.c b/r_part.c index 5a1a361d..6fcb7ba7 100644 --- a/r_part.c +++ b/r_part.c @@ -46,7 +46,7 @@ CL_DrawParticles update particle color, position, free expired and draw it ================ */ -void CL_DrawParticles( double frametime, particle_t *cl_active_particles, float partsize ) +void GAME_EXPORT CL_DrawParticles( double frametime, particle_t *cl_active_particles, float partsize ) { particle_t *p; vec3_t right, up; @@ -162,7 +162,7 @@ CL_DrawTracers update tracer color, position, free expired and draw it ================ */ -void CL_DrawTracers( double frametime, particle_t *cl_active_tracers ) +void GAME_EXPORT CL_DrawTracers( double frametime, particle_t *cl_active_tracers ) { float scale, atten, gravity; vec3_t screenLast, screen; @@ -288,7 +288,7 @@ CL_DrawParticlesExternal allow to draw effects from custom renderer =============== */ -void CL_DrawParticlesExternal( const ref_viewpass_t *rvp, qboolean trans_pass, float frametime ) +void GAME_EXPORT CL_DrawParticlesExternal( const ref_viewpass_t *rvp, qboolean trans_pass, float frametime ) { ref_instance_t oldRI = RI; diff --git a/r_sprite.c b/r_sprite.c index f28816a0..512c06f3 100644 --- a/r_sprite.c +++ b/r_sprite.c @@ -236,7 +236,7 @@ Loading a bitmap image as sprite with multiple frames as pieces of input image ==================== */ -void Mod_LoadMapSprite( model_t *mod, const void *buffer, size_t size, qboolean *loaded ) +void GAME_EXPORT Mod_LoadMapSprite( model_t *mod, const void *buffer, size_t size, qboolean *loaded ) { byte *src, *dst; rgbdata_t *pix, temp; diff --git a/r_studio.c b/r_studio.c index 584acbe2..0a69142e 100644 --- a/r_studio.c +++ b/r_studio.c @@ -555,7 +555,7 @@ R_StudioLerpMovement ==================== */ -void R_StudioLerpMovement( cl_entity_t *e, double time, vec3_t origin, vec3_t angles ) +void GAME_EXPORT R_StudioLerpMovement( cl_entity_t *e, double time, vec3_t origin, vec3_t angles ) { float f = 1.0f; @@ -621,7 +621,7 @@ StudioEstimateFrame ==================== */ -float R_StudioEstimateFrame( cl_entity_t *e, mstudioseqdesc_t *pseqdesc ) +float GAME_EXPORT R_StudioEstimateFrame( cl_entity_t *e, mstudioseqdesc_t *pseqdesc ) { double dfdt, f; @@ -1840,7 +1840,7 @@ R_StudioGetTexture Doesn't changes studio global state at all =============== */ -mstudiotexture_t *R_StudioGetTexture( cl_entity_t *e ) +mstudiotexture_t * GAME_EXPORT R_StudioGetTexture( cl_entity_t *e ) { mstudiotexture_t *ptexture; studiohdr_t *phdr, *thdr; @@ -3609,7 +3609,7 @@ static void R_StudioLoadTexture( model_t *mod, studiohdr_t *phdr, mstudiotexture Mod_StudioLoadTextures ================= */ -void Mod_StudioLoadTextures( model_t *mod, void *data ) +void GAME_EXPORT Mod_StudioLoadTextures( model_t *mod, void *data ) { studiohdr_t *phdr = (studiohdr_t *)data; mstudiotexture_t *ptexture; @@ -3745,7 +3745,7 @@ CL_InitStudioAPI Initialize client studio =============== */ -void CL_InitStudioAPI( void ) +void GAME_EXPORT CL_InitStudioAPI( void ) { pStudioDraw = &gStudioDraw; diff --git a/r_triapi.c b/r_triapi.c index f623512e..ba3981db 100644 --- a/r_triapi.c +++ b/r_triapi.c @@ -43,7 +43,7 @@ TriRenderMode set rendermode ============= */ -void TriRenderMode( int mode ) +void GAME_EXPORT TriRenderMode( int mode ) { ds.renderMode = vid.rendermode = mode; #if 0 @@ -82,7 +82,7 @@ TriBegin begin triangle sequence ============= */ -void TriBegin( int mode1 ) +void GAME_EXPORT TriBegin( int mode1 ) { #if 0 switch( mode ) @@ -129,7 +129,7 @@ TriEnd draw triangle sequence ============= */ -void TriEnd( void ) +void GAME_EXPORT TriEnd( void ) { //if( vertcount == 3 ) //pglEnd( ); @@ -141,7 +141,7 @@ _TriColor4f ============= */ -void _TriColor4f( float rr, float gg, float bb, float aa ) +void GAME_EXPORT _TriColor4f( float rr, float gg, float bb, float aa ) { //pglColor4f( r, g, b, a ); unsigned short r,g,b; @@ -207,7 +207,7 @@ TriColor4ub ============= */ -void _TriColor4ub( byte r, byte g, byte b, byte a ) +void GAME_EXPORT _TriColor4ub( byte r, byte g, byte b, byte a ) { _TriColor4f( r * (1.0f / 255.0f), g * (1.0f / 255.0f), @@ -240,7 +240,7 @@ TriTexCoord2f ============= */ -void TriTexCoord2f( volatile float u, volatile float v ) +void GAME_EXPORT TriTexCoord2f( volatile float u, volatile float v ) { volatile double u1 = 0, v1 = 0; u = fmodf(u, 10); @@ -270,7 +270,7 @@ TriVertex3fv ============= */ -void TriVertex3fv( const float *v ) +void GAME_EXPORT TriVertex3fv( const float *v ) { //pglVertex3fv( v ); TriVertex3f( v[0], v[1], v[2] ); @@ -282,7 +282,7 @@ TriVertex3f ============= */ -void TriVertex3f( float x, float y, float z ) +void GAME_EXPORT TriVertex3f( float x, float y, float z ) { if( mode == TRI_TRIANGLES ) { @@ -354,7 +354,7 @@ TriWorldToScreen convert world coordinates (x,y,z) into screen (x, y) ============= */ -int TriWorldToScreen( const float *world, float *screen ) +int GAME_EXPORT TriWorldToScreen( const float *world, float *screen ) { int retval; @@ -398,7 +398,7 @@ TriFog enables global fog on the level ============= */ -void TriFog( float flFogColor[3], float flStart, float flEnd, int bOn ) +void GAME_EXPORT TriFog( float flFogColor[3], float flStart, float flEnd, int bOn ) { #if 0 // overrided by internal fog @@ -442,7 +442,7 @@ TriGetMatrix very strange export ============= */ -void TriGetMatrix( const int pname, float *matrix ) +void GAME_EXPORT TriGetMatrix( const int pname, float *matrix ) { //pglGetFloatv( pname, matrix ); } @@ -453,7 +453,7 @@ TriForParams ============= */ -void TriFogParams( float flDensity, int iFogSkybox ) +void GAME_EXPORT TriFogParams( float flDensity, int iFogSkybox ) { //RI.fogDensity = flDensity; //RI.fogSkybox = iFogSkybox; @@ -465,7 +465,7 @@ TriCullFace ============= */ -void TriCullFace( TRICULLSTYLE mode ) +void GAME_EXPORT TriCullFace( TRICULLSTYLE mode ) { #if 0 int glMode; From c293a7a26d107409e7dea959fec0a0e8edf19363 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 13 Apr 2019 19:14:07 +0700 Subject: [PATCH 080/115] ref_soft: update wscript --- wscript | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/wscript b/wscript index a4e4b2c6..93933140 100644 --- a/wscript +++ b/wscript @@ -4,7 +4,6 @@ from waflib import Logs import os -from fwgslib import get_subproject_name top = '.' @@ -26,10 +25,6 @@ def build(bld): if bld.env.DEDICATED: return - bld.load_envs() - name = get_subproject_name(bld) - bld.env = bld.all_envs[name] - libs = [ 'public', 'M' ] source = bld.path.ant_glob(['*.c']) @@ -45,7 +40,7 @@ def build(bld): bld.shlib( source = source, - target = name, + target = 'ref_soft', features = 'c', includes = includes, use = libs, From b2105a113c5f367f41719f4c0f76a6b13d77d501 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 13 Apr 2019 19:15:26 +0700 Subject: [PATCH 081/115] ref_soft: extended bsp support --- r_edge.c | 18 ++++++++++-------- r_surf.c | 40 ++++++++++++++++++++++++++-------------- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/r_edge.c b/r_edge.c index 4c9a3d16..cf10f868 100644 --- a/r_edge.c +++ b/r_edge.c @@ -821,8 +821,8 @@ void D_CalcGradients (msurface_t *pface) mipscale = 1.0 / (float)(1 << miplevel); - TransformVector (pface->texinfo->vecs[0], p_saxis); - TransformVector (pface->texinfo->vecs[1], p_taxis); + TransformVector (pface->info->lmvecs[0], p_saxis); + TransformVector (pface->info->lmvecs[1], p_taxis); t = xscaleinv * mipscale; d_sdivzstepu = p_saxis[0] * t; @@ -841,11 +841,11 @@ void D_CalcGradients (msurface_t *pface) t = 0x10000*mipscale; sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) - - ((pface->texturemins[0] << 16) >> miplevel) - + pface->texinfo->vecs[0][3]*t; + ((pface->info->lightmapmins[0] << 16) >> miplevel) + + pface->info->lmvecs[0][3]*t; tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - - ((pface->texturemins[1] << 16) >> miplevel) - + pface->texinfo->vecs[1][3]*t; + ((pface->info->lightmapmins[1] << 16) >> miplevel) + + pface->info->lmvecs[1][3]*t; #if 1 // PGM - changing flow speed for non-warping textures. if (pface->flags & SURF_CONVEYOR) @@ -861,8 +861,8 @@ void D_CalcGradients (msurface_t *pface) // // -1 (-epsilon) so we never wander off the edge of the texture // - bbextents = ((pface->extents[0] << 16) >> miplevel) - 1; - bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1; + bbextents = ((pface->info->lightextents[0] << 16) >> miplevel) - 1; + bbextentt = ((pface->info->lightextents[1] << 16) >> miplevel) - 1; } @@ -1149,6 +1149,8 @@ void D_SolidSurf (surf_t *s) miplevel = 1; else miplevel = D_MipLevelForScale(s->nearzi * scale_for_mip ); + while( 1 << miplevel > gEngfuncs.Mod_SampleSizeForFace(pface)) + miplevel--; #else { float dot; diff --git a/r_surf.c b/r_surf.c index db6aafa2..ce6f2823 100644 --- a/r_surf.c +++ b/r_surf.c @@ -484,9 +484,17 @@ void R_DrawSurface (void) pixel_t *pcolumndest; void (*pblockdrawer)(void); image_t *mt; + uint sample_size, sample_bits, sample_pot; surfrowbytes = r_drawsurf.rowbytes; + sample_size = gEngfuncs.Mod_SampleSizeForFace( r_drawsurf.surf ); + sample_bits = 0; + for( sample_pot = 1; sample_pot < sample_size; sample_pot <<= 1, sample_bits++ ); + + + //printf("%d\n", sample_size ); + mt = r_drawsurf.image; r_source = mt->pixels[r_drawsurf.surfmip]; @@ -496,8 +504,8 @@ void R_DrawSurface (void) texwidth = mt->width >> r_drawsurf.surfmip; - blocksize = 16 >> r_drawsurf.surfmip; - blockdivshift = 4 - r_drawsurf.surfmip; + blocksize = sample_pot >> r_drawsurf.surfmip; + blockdivshift = sample_bits - r_drawsurf.surfmip; blockdivmask = (1 << blockdivshift) - 1; r_lightwidth = ( r_drawsurf.surf->info->lightextents[0] / gEngfuncs.Mod_SampleSizeForFace( r_drawsurf.surf ) ) + 1; @@ -520,8 +528,10 @@ void R_DrawSurface (void) r_sourcemax = r_source + (tmax * smax); - soffset = r_drawsurf.surf->texturemins[0]; - basetoffset = r_drawsurf.surf->texturemins[1]; + //soffset = r_drawsurf.surf->texturemins[0]; + //basetoffset = r_drawsurf.surf->texturemins[1]; + soffset = r_drawsurf.surf->info->lightmapmins[0]; + basetoffset = r_drawsurf.surf->info->lightmapmins[1]; // << 16 components are to guarantee positive values for % soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax; @@ -580,14 +590,14 @@ void R_DrawSurfaceBlock8_mip0 (void) lightleftstep = (r_lightptr[0] - lightleft) >> 4; lightrightstep = (r_lightptr[1] - lightright) >> 4; - for (i=0 ; i<16 ; i++) + for (i=0 ; i> 4; light = lightright; - for (b=15; b>=0; b--) + for (b=blocksize - 1; b>=0; b--) { pix = psource[b]; prowdest[b] = BLEND_LM(pix, light); @@ -636,14 +646,14 @@ void R_DrawSurfaceBlock8_mip1 (void) lightleftstep = (r_lightptr[0] - lightleft) >> 3; lightrightstep = (r_lightptr[1] - lightright) >> 3; - for (i=0 ; i<8 ; i++) + for (i=0 ; i> 3; light = lightright; - for (b=7; b>=0; b--) + for (b=blocksize-1; b>=0; b--) { pix = psource[b]; prowdest[b] = BLEND_LM(pix, light); @@ -688,14 +698,14 @@ void R_DrawSurfaceBlock8_mip2 (void) lightleftstep = (r_lightptr[0] - lightleft) >> 2; lightrightstep = (r_lightptr[1] - lightright) >> 2; - for (i=0 ; i<4 ; i++) + for (i=0 ; i> 2; light = lightright; - for (b=3; b>=0; b--) + for (b=blocksize-1; b>=0; b--) { pix = psource[b]; prowdest[b] = BLEND_LM(pix, light);; @@ -740,14 +750,14 @@ void R_DrawSurfaceBlock8_mip3 (void) lightleftstep = (r_lightptr[0] - lightleft) >> 1; lightrightstep = (r_lightptr[1] - lightright) >> 1; - for (i=0 ; i<2 ; i++) + for (i=0 ; i> 1; light = lightright; - for (b=1; b>=0; b--) + for (b=blocksize-1; b>=0; b--) { pix = psource[b]; prowdest[b] = BLEND_LM(pix, light);; @@ -1184,9 +1194,11 @@ surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) // surfscale = 1.0 / (1<extents[0] >> miplevel; + r_drawsurf.surfwidth = surface->info->lightextents[0] >> miplevel; + //surface->extents[0] >> miplevel; r_drawsurf.rowbytes = r_drawsurf.surfwidth; - r_drawsurf.surfheight = surface->extents[1] >> miplevel; + r_drawsurf.surfheight = surface->info->lightextents[1] >> miplevel; + //surface->extents[1] >> miplevel; // From 60e3a78221ef254bfb4ad1572bd5ad64d73c02fa Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 13 Apr 2019 20:49:07 +0700 Subject: [PATCH 082/115] ref_soft: Implement texture free --- r_image.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/r_image.c b/r_image.c index 1744346c..e38b9353 100644 --- a/r_image.c +++ b/r_image.c @@ -886,11 +886,12 @@ static void GL_DeleteTexture( image_t *tex ) { image_t **prev; image_t *cur; + int i; ASSERT( tex != NULL ); // already freed? - if( !tex->pixels) return; + if( !tex->pixels[0]) return; // debug if( !tex->name[0] ) @@ -919,6 +920,10 @@ static void GL_DeleteTexture( image_t *tex ) if( tex->original ) gEngfuncs.FS_FreeImage( tex->original ); + for( i = 0; i < 4; i++ ) + if( tex->pixels[i]) Mem_Free(tex->pixels[i]); + if( tex->alpha_pixels ) Mem_Free(tex->alpha_pixels); + memset( tex, 0, sizeof( *tex )); } From ee67d350e3cf88dc893d724f394ad8e8847765f2 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 13 Apr 2019 20:50:27 +0700 Subject: [PATCH 083/115] ref_soft: Fix world unload. Improve lightmap sample detection --- r_context.c | 10 +++-- r_edge.c | 10 ++--- r_local.h | 7 ++++ r_main.c | 36 +++++++++++++++- r_surf.c | 119 ++++++++++++++++++++++++++++++++++++++++++---------- 5 files changed, 147 insertions(+), 35 deletions(-) diff --git a/r_context.c b/r_context.c index 101d093a..f13b8825 100644 --- a/r_context.c +++ b/r_context.c @@ -123,7 +123,7 @@ static void GAME_EXPORT CL_FillRGBABlend( float _x, float _y, float _w, float _h _TriColor4ub(r,g,b,a); Draw_Fill(_x,_y,_w,_h); } - +void Mod_UnloadTextures( model_t *mod ); qboolean GAME_EXPORT Mod_ProcessRenderData( model_t *mod, qboolean create, const byte *buf ) { @@ -155,8 +155,8 @@ qboolean GAME_EXPORT Mod_ProcessRenderData( model_t *mod, qboolean create, const if( loaded && gEngfuncs.drawFuncs->Mod_ProcessUserData ) gEngfuncs.drawFuncs->Mod_ProcessUserData( mod, create, buf ); - //if( !create ) - //Mod_UnloadTextures( mod ); + if( !create ) + Mod_UnloadTextures( mod ); return loaded; } @@ -281,6 +281,10 @@ void Mod_BrushUnloadTextures( model_t *mod ) { int i; + + gEngfuncs.Con_Printf("Unloading world\n"); + tr.map_unload = true; + for( i = 0; i < mod->numtextures; i++ ) { texture_t *tx = mod->textures[i]; diff --git a/r_edge.c b/r_edge.c index cf10f868..e48495ca 100644 --- a/r_edge.c +++ b/r_edge.c @@ -846,7 +846,6 @@ void D_CalcGradients (msurface_t *pface) tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - ((pface->info->lightmapmins[1] << 16) >> miplevel) + pface->info->lmvecs[1][3]*t; -#if 1 // PGM - changing flow speed for non-warping textures. if (pface->flags & SURF_CONVEYOR) { @@ -855,13 +854,10 @@ void D_CalcGradients (msurface_t *pface) sadjust += 0x10000 * (-128 * ( (gpGlobals->time * 0.25) - (int)(gpGlobals->time * 0.25) )); else sadjust += 0x10000 * (-128 * ( (gpGlobals->time * 0.77) - (int)(gpGlobals->time * 0.77) )); + bbextents = ((pface->extents[0] << 16) >> miplevel) - 1; } - // PGM -#endif -// -// -1 (-epsilon) so we never wander off the edge of the texture -// - bbextents = ((pface->info->lightextents[0] << 16) >> miplevel) - 1; + else + bbextents = ((pface->info->lightextents[0] << 16) >> miplevel) - 1; bbextentt = ((pface->info->lightextents[1] << 16) >> miplevel) - 1; } diff --git a/r_local.h b/r_local.h index ad3bf50a..dc6e7acf 100644 --- a/r_local.h +++ b/r_local.h @@ -294,6 +294,9 @@ typedef struct qboolean fCustomSkybox; char mapname[MAX_STRING]; + int sample_size; + uint sample_bits; + qboolean map_unload; } gl_globals_t; typedef struct @@ -1285,6 +1288,10 @@ void R_SetUpWorldTransform (void); #define BLEND_ADD(src, screen) vid.addmap[ src& 0xff00|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 0); #define BLEND_COLOR(src, color) vid.modmap[src & 0xff00|(color>>8)] << 8 | (src & color & 0xff) | ((src & 0xff) >> 3); +#define LM_SAMPLE_SIZE_AUTO(surf) (tr.sample_size == -1?gEngfuncs.Mod_SampleSizeForFace( surf ): tr.sample_size) + + + // // engine callbacks // diff --git a/r_main.c b/r_main.c index c50538be..f1103a4d 100644 --- a/r_main.c +++ b/r_main.c @@ -1594,6 +1594,12 @@ void GAME_EXPORT R_RenderScene( void ) // begin a new frame tr.framecount++; + if( tr.map_unload ) + { + D_FlushCaches(); + tr.map_unload = false; + } + R_SetupFrustum(); R_SetupFrame(); @@ -1824,6 +1830,7 @@ void GAME_EXPORT R_NewMap (void) { int i; r_viewcluster = -1; + model_t *world = WORLDMODEL; tr.draw_list->num_solid_entities = 0; tr.draw_list->num_trans_entities = 0; @@ -1871,8 +1878,33 @@ void GAME_EXPORT R_NewMap (void) } // clear out efrags in case the level hasn't been reloaded - for( i = 0; i < WORLDMODEL->numleafs; i++ ) - WORLDMODEL->leafs[i+1].efrags = NULL; + for( i = 0; i < world->numleafs; i++ ) + world->leafs[i+1].efrags = NULL; + + tr.sample_size = gEngfuncs.Mod_SampleSizeForFace( &world->surfaces[0] ); + + for( i = 1; i < world->numsurfaces; i++ ) + { + int sample_size = gEngfuncs.Mod_SampleSizeForFace( &world->surfaces[i] ); + if( sample_size != tr.sample_size ) + { + tr.sample_size = -1; + break; + } + } + tr.sample_bits = -1; + + if( tr.sample_size != -1 ) + { + uint sample_pot; + + tr.sample_bits = 0; + + for( sample_pot = 1; sample_pot < tr.sample_size; sample_pot <<= 1, tr.sample_bits++ ); + } + + gEngfuncs.Con_Printf("Map sample size is %d\n", tr.sample_size ); + } /* diff --git a/r_surf.c b/r_surf.c index ce6f2823..4a95293a 100644 --- a/r_surf.c +++ b/r_surf.c @@ -40,6 +40,7 @@ void R_DrawSurfaceBlock8_mip0 (void); void R_DrawSurfaceBlock8_mip1 (void); void R_DrawSurfaceBlock8_mip2 (void); void R_DrawSurfaceBlock8_mip3 (void); +void R_DrawSurfaceBlock8_Generic (void); static void (*surfmiptable[4])(void) = { R_DrawSurfaceBlock8_mip0, @@ -488,12 +489,21 @@ void R_DrawSurface (void) surfrowbytes = r_drawsurf.rowbytes; - sample_size = gEngfuncs.Mod_SampleSizeForFace( r_drawsurf.surf ); - sample_bits = 0; - for( sample_pot = 1; sample_pot < sample_size; sample_pot <<= 1, sample_bits++ ); - + sample_size = LM_SAMPLE_SIZE_AUTO(r_drawsurf.surf); + if( sample_size == 16 ) + sample_bits = 4, sample_pot = sample_size; + else + { + sample_bits = tr.sample_bits; - //printf("%d\n", sample_size ); + if( sample_bits == -1 ) + { + sample_bits = 0; + for( sample_pot = 1; sample_pot < sample_size; sample_pot <<= 1, sample_bits++ ); + } + else + sample_pot = 1 << sample_bits; + } mt = r_drawsurf.image; @@ -508,15 +518,21 @@ void R_DrawSurface (void) blockdivshift = sample_bits - r_drawsurf.surfmip; blockdivmask = (1 << blockdivshift) - 1; - r_lightwidth = ( r_drawsurf.surf->info->lightextents[0] / gEngfuncs.Mod_SampleSizeForFace( r_drawsurf.surf ) ) + 1; - //r_lightwidth = (r_drawsurf.surf->extents[0]>>4)+1; + if( sample_size == 16 ) + r_lightwidth = ( r_drawsurf.surf->info->lightextents[0]>>4)+1; + else + r_lightwidth = ( r_drawsurf.surf->info->lightextents[0] / sample_size ) + 1; r_numhblocks = r_drawsurf.surfwidth >> blockdivshift; r_numvblocks = r_drawsurf.surfheight >> blockdivshift; //============================== - pblockdrawer = surfmiptable[r_drawsurf.surfmip]; + if( sample_size == 16 ) + pblockdrawer = surfmiptable[r_drawsurf.surfmip]; + else + pblockdrawer = R_DrawSurfaceBlock8_Generic; + // TODO: only needs to be set when there is a display settings change horzblockstep = blocksize; @@ -566,6 +582,61 @@ void R_DrawSurface (void) #if !id386 #define BLEND_LM(pix, light) vid.colormap[(pix >> 3) | ((light & 0x1f00) << 5)] | pix & 7; + +/* +================ +R_DrawSurfaceBlock8_Generic +================ +*/ +void R_DrawSurfaceBlock8_Generic (void) +{ + int v, i, b; + uint lightstep, lighttemp, light; + pixel_t pix, *psource, *prowdest; + + psource = pbasesource; + prowdest = prowdestbase; + + for (v=0 ; v> (4-r_drawsurf.surfmip); + lightrightstep = (r_lightptr[1] - lightright) >> (4-r_drawsurf.surfmip); + + for (i=0 ; i> (4-r_drawsurf.surfmip); + + light = lightright; + + for (b=blocksize-1; b>=0; b--) + { + pix = psource[b]; + prowdest[b] = BLEND_LM(pix, light); + if( pix == TRANSPARENT_COLOR ) + prowdest[b] = TRANSPARENT_COLOR; + //((unsigned char *)vid.colormap) + //[(light & 0xFF00) + pix]; + light += lightstep; + } + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += surfrowbytes; + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + + /* ================ R_DrawSurfaceBlock8_mip0 @@ -590,14 +661,14 @@ void R_DrawSurfaceBlock8_mip0 (void) lightleftstep = (r_lightptr[0] - lightleft) >> 4; lightrightstep = (r_lightptr[1] - lightright) >> 4; - for (i=0 ; i> 4; light = lightright; - for (b=blocksize - 1; b>=0; b--) + for (b=15; b>=0; b--) { pix = psource[b]; prowdest[b] = BLEND_LM(pix, light); @@ -646,14 +717,14 @@ void R_DrawSurfaceBlock8_mip1 (void) lightleftstep = (r_lightptr[0] - lightleft) >> 3; lightrightstep = (r_lightptr[1] - lightright) >> 3; - for (i=0 ; i> 3; light = lightright; - for (b=blocksize-1; b>=0; b--) + for (b=7; b>=0; b--) { pix = psource[b]; prowdest[b] = BLEND_LM(pix, light); @@ -698,14 +769,14 @@ void R_DrawSurfaceBlock8_mip2 (void) lightleftstep = (r_lightptr[0] - lightleft) >> 2; lightrightstep = (r_lightptr[1] - lightright) >> 2; - for (i=0 ; i> 2; light = lightright; - for (b=blocksize-1; b>=0; b--) + for (b=3; b>=0; b--) { pix = psource[b]; prowdest[b] = BLEND_LM(pix, light);; @@ -750,14 +821,14 @@ void R_DrawSurfaceBlock8_mip3 (void) lightleftstep = (r_lightptr[0] - lightleft) >> 1; lightrightstep = (r_lightptr[1] - lightright) >> 1; - for (i=0 ; i> 1; light = lightright; - for (b=blocksize-1; b>=0; b--) + for (b=1; b>=0; b--) { pix = psource[b]; prowdest[b] = BLEND_LM(pix, light);; @@ -840,7 +911,7 @@ void D_FlushCaches( void ) qboolean newmap = !world || !Q_strcmp( tr.mapname, WORLDMODEL->name ); // if newmap, surfaces already freed - if( !newmap ) + if( !newmap && !tr.map_unload ) { for(c = sc_base ; c ; c = c->next ) { @@ -1141,13 +1212,13 @@ surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) { if( miplevel >= 1) { - surface->extents[0] = surface->info->lightextents[0] * gEngfuncs.Mod_SampleSizeForFace( r_drawsurf.surf ) * 2 ; - surface->texturemins[0] = -surface->info->lightextents[0] * gEngfuncs.Mod_SampleSizeForFace( r_drawsurf.surf ); + surface->extents[0] = surface->info->lightextents[0] * LM_SAMPLE_SIZE_AUTO( r_drawsurf.surf ) * 2 ; + surface->info->lightmapmins[0] = -surface->info->lightextents[0] * LM_SAMPLE_SIZE_AUTO( r_drawsurf.surf ); } else { - surface->extents[0] = surface->info->lightextents[0] * gEngfuncs.Mod_SampleSizeForFace( r_drawsurf.surf ) ; - surface->texturemins[0] = -surface->info->lightextents[0] * gEngfuncs.Mod_SampleSizeForFace( r_drawsurf.surf )/2; + surface->extents[0] = surface->info->lightextents[0] * LM_SAMPLE_SIZE_AUTO( r_drawsurf.surf ) ; + surface->info->lightmapmins[0] = -surface->info->lightextents[0] * LM_SAMPLE_SIZE_AUTO( r_drawsurf.surf )/2; } } /// todo: port this @@ -1194,8 +1265,10 @@ surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) // surfscale = 1.0 / (1<info->lightextents[0] >> miplevel; - //surface->extents[0] >> miplevel; + if( surface->flags & SURF_CONVEYOR ) + r_drawsurf.surfwidth = surface->extents[0] >> miplevel; + else + r_drawsurf.surfwidth = surface->info->lightextents[0] >> miplevel; r_drawsurf.rowbytes = r_drawsurf.surfwidth; r_drawsurf.surfheight = surface->info->lightextents[1] >> miplevel; //surface->extents[1] >> miplevel; From 1c0262a8c4a64e8ab0de8f879193fc605b6571dc Mon Sep 17 00:00:00 2001 From: mittorn Date: Sun, 14 Apr 2019 00:58:14 +0700 Subject: [PATCH 084/115] ref_soft: Partial world luxels support --- r_bsp.c | 8 ++-- r_edge.c | 29 ++++++++++++- r_surf.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 149 insertions(+), 14 deletions(-) diff --git a/r_bsp.c b/r_bsp.c index 01229af4..d78efbcc 100644 --- a/r_bsp.c +++ b/r_bsp.c @@ -35,8 +35,8 @@ int r_currentbkey; typedef enum {touchessolid, drawnode, nodrawnode} solidstate_t; -#define MAX_BMODEL_VERTS 500 // 6K -#define MAX_BMODEL_EDGES 1000 // 12K +#define MAX_BMODEL_VERTS 1000 // 12K +#define MAX_BMODEL_EDGES 2000 // 24K static mvertex_t *pbverts; static bedge_t *pbedges; @@ -421,7 +421,7 @@ void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) // FIXME: share the clip edge by having a winding direction flag? if (numbedges >= (MAX_BMODEL_EDGES - 1)) { - gEngfuncs.Con_Printf ("Out of edges for bmodel\n"); + //gEngfuncs.Con_Printf ("Out of edges for bmodel\n"); return; } @@ -465,7 +465,7 @@ void R_RecursiveClipBPoly (bedge_t *pedges, mnode_t *pnode, msurface_t *psurf) { if (numbedges >= (MAX_BMODEL_EDGES - 2)) { - gEngfuncs.Con_Printf ("Out of edges for bmodel\n"); + //gEngfuncs.Con_Printf ("Out of edges for bmodel\n"); return; } diff --git a/r_edge.c b/r_edge.c index e48495ca..97cc7985 100644 --- a/r_edge.c +++ b/r_edge.c @@ -821,8 +821,17 @@ void D_CalcGradients (msurface_t *pface) mipscale = 1.0 / (float)(1 << miplevel); + + if( pface->texinfo->flags & TEX_WORLD_LUXELS ) + { + TransformVector (pface->texinfo->vecs[0], p_saxis); + TransformVector (pface->texinfo->vecs[1], p_taxis); + } + else + { TransformVector (pface->info->lmvecs[0], p_saxis); TransformVector (pface->info->lmvecs[1], p_taxis); + } t = xscaleinv * mipscale; d_sdivzstepu = p_saxis[0] * t; @@ -840,12 +849,24 @@ void D_CalcGradients (msurface_t *pface) VectorScale (transformed_modelorg, mipscale, p_temp1); t = 0x10000*mipscale; + if( pface->texinfo->flags & TEX_WORLD_LUXELS ) + { + sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) - + ((pface->texturemins[0] << 16) >> miplevel) + + pface->texinfo->vecs[0][3]*t; + tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - + ((pface->texturemins[1] << 16) >> miplevel) + + pface->texinfo->vecs[1][3]*t; + } + else + { sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) - ((pface->info->lightmapmins[0] << 16) >> miplevel) + pface->info->lmvecs[0][3]*t; tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - ((pface->info->lightmapmins[1] << 16) >> miplevel) + pface->info->lmvecs[1][3]*t; + } // PGM - changing flow speed for non-warping textures. if (pface->flags & SURF_CONVEYOR) { @@ -859,6 +880,12 @@ void D_CalcGradients (msurface_t *pface) else bbextents = ((pface->info->lightextents[0] << 16) >> miplevel) - 1; bbextentt = ((pface->info->lightextents[1] << 16) >> miplevel) - 1; + + if( pface->texinfo->flags & TEX_WORLD_LUXELS ) + { + bbextents = ((pface->extents[0] << 16) >> miplevel) - 1; + bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1; + } } @@ -1139,8 +1166,6 @@ void D_SolidSurf (surf_t *s) if( !pface ) return; #if 1 - - if( pface->flags & SURF_CONVEYOR ) miplevel = 1; else diff --git a/r_surf.c b/r_surf.c index 4a95293a..23e5efa0 100644 --- a/r_surf.c +++ b/r_surf.c @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // r_surf.c: surface-related refresh code #include "r_local.h" +#include "mod_local.h" drawsurf_t r_drawsurf; @@ -41,6 +42,9 @@ void R_DrawSurfaceBlock8_mip1 (void); void R_DrawSurfaceBlock8_mip2 (void); void R_DrawSurfaceBlock8_mip3 (void); void R_DrawSurfaceBlock8_Generic (void); +void R_DrawSurfaceBlock8_World (void); + +static float worldlux_s, worldlux_t; static void (*surfmiptable[4])(void) = { R_DrawSurfaceBlock8_mip0, @@ -93,8 +97,8 @@ void R_AddDynamicLights( msurface_t *surf ) { if( surf->texinfo->faceinfo ) sample_frac = surf->texinfo->faceinfo->texture_step; - //else if( FBitSet( surf->texinfo->flags, TEX_EXTRA_LIGHTMAP )) - // sample_frac = LM_SAMPLE_EXTRASIZE; + else if( FBitSet( surf->texinfo->flags, TEX_EXTRA_LIGHTMAP )) + sample_frac = LM_SAMPLE_EXTRASIZE; else sample_frac = LM_SAMPLE_SIZE; } @@ -504,7 +508,6 @@ void R_DrawSurface (void) else sample_pot = 1 << sample_bits; } - mt = r_drawsurf.image; r_source = mt->pixels[r_drawsurf.surfmip]; @@ -526,6 +529,7 @@ void R_DrawSurface (void) r_numhblocks = r_drawsurf.surfwidth >> blockdivshift; r_numvblocks = r_drawsurf.surfheight >> blockdivshift; + //============================== if( sample_size == 16 ) @@ -544,8 +548,46 @@ void R_DrawSurface (void) r_sourcemax = r_source + (tmax * smax); - //soffset = r_drawsurf.surf->texturemins[0]; - //basetoffset = r_drawsurf.surf->texturemins[1]; + // glitchy and slow way to draw some lightmap + if( r_drawsurf.surf->texinfo->flags & TEX_WORLD_LUXELS ) + { + worldlux_s = r_drawsurf.surf->extents[0] / r_drawsurf.surf->info->lightextents[0]; + worldlux_t = r_drawsurf.surf->extents[1] / r_drawsurf.surf->info->lightextents[1]; + if( worldlux_s == 0 ) + worldlux_s = 1; + if( worldlux_t == 0 ) + worldlux_t = 1; + + soffset = r_drawsurf.surf->texturemins[0]; + basetoffset = r_drawsurf.surf->texturemins[1]; + //soffset = r_drawsurf.surf->info->lightmapmins[0] * worldlux_s; + //basetoffset = r_drawsurf.surf->info->lightmapmins[1] * worldlux_t; + // << 16 components are to guarantee positive values for % + soffset = ((soffset >> r_drawsurf.surfmip) + (smax << 16)) % smax; + basetptr = &r_source[((((basetoffset >> r_drawsurf.surfmip) + + (tmax << 16)) % tmax) * twidth)]; + + pcolumndest = r_drawsurf.surfdat; + + for (u=0 ; u= smax) + soffset = 0; + + pcolumndest += horzblockstep; + } + return; + } + soffset = r_drawsurf.surf->info->lightmapmins[0]; basetoffset = r_drawsurf.surf->info->lightmapmins[1]; @@ -566,7 +608,7 @@ void R_DrawSurface (void) (*pblockdrawer)(); - soffset = soffset + blocksize; + soffset = soffset + horzblockstep; if (soffset >= smax) soffset = 0; @@ -582,6 +624,63 @@ void R_DrawSurface (void) #if !id386 #define BLEND_LM(pix, light) vid.colormap[(pix >> 3) | ((light & 0x1f00) << 5)] | pix & 7; +/* +================ +R_DrawSurfaceBlock8_World + +Does not draw lightmap correclty, but scale it correctly. Better than nothing +================ +*/ +void R_DrawSurfaceBlock8_World (void) +{ + int v, i, b; + uint lightstep, lighttemp, light; + pixel_t pix, *psource, *prowdest; + int lightpos = 0; + + psource = pbasesource; + prowdest = prowdestbase; + + for (v=0 ; v> (4-r_drawsurf.surfmip); + lightrightstep =(r_lightptr[(lightpos/r_lightwidth) * r_lightwidth+1] - lightright) >> (4-r_drawsurf.surfmip); + + for (i=0 ; i> (4-r_drawsurf.surfmip); + + light = lightright; + + for (b=blocksize-1; b>=0; b--) + { + //pix = psource[(uint)(b * worldlux_s)]; + pix = psource[b]; + prowdest[b] = BLEND_LM(pix, light); + if( pix == TRANSPARENT_COLOR ) + prowdest[b] = TRANSPARENT_COLOR; + //((unsigned char *)vid.colormap) + //[(light & 0xFF00) + pix]; + light += lightstep; + } + + psource += sourcetstep; + lightright += lightrightstep; + lightleft += lightleftstep; + prowdest += surfrowbytes; + } + + if (psource >= r_sourcemax) + psource -= r_stepback; + } +} + /* ================ @@ -1208,7 +1307,11 @@ surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) // r_drawsurf.image = R_GetTexture(R_TextureAnimation (surface)->gl_texturenum); - if( surface->flags & SURF_CONVEYOR ) + // does not support conveyors with world luxels now + if( surface->texinfo->flags & TEX_WORLD_LUXELS ) + surface->flags &= ~SURF_CONVEYOR; + + if( surface->flags & SURF_CONVEYOR) { if( miplevel >= 1) { @@ -1271,7 +1374,14 @@ surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel) r_drawsurf.surfwidth = surface->info->lightextents[0] >> miplevel; r_drawsurf.rowbytes = r_drawsurf.surfwidth; r_drawsurf.surfheight = surface->info->lightextents[1] >> miplevel; - //surface->extents[1] >> miplevel; + + // use texture space if world luxels used + if( surface->texinfo->flags & TEX_WORLD_LUXELS ) + { + r_drawsurf.surfwidth = surface->extents[0] >> miplevel; + r_drawsurf.rowbytes = r_drawsurf.surfwidth; + r_drawsurf.surfheight = surface->extents[1] >> miplevel; + } // From 8a99d64139df3a3bec26a156b7f5d889bb0a8ea1 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sun, 14 Apr 2019 06:20:22 +0700 Subject: [PATCH 085/115] ref_soft: fix blocksize --- r_surf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/r_surf.c b/r_surf.c index 23e5efa0..a16256dc 100644 --- a/r_surf.c +++ b/r_surf.c @@ -579,7 +579,7 @@ void R_DrawSurface (void) R_DrawSurfaceBlock8_World(); - soffset = soffset + horzblockstep; + soffset = soffset + blocksize; if (soffset >= smax) soffset = 0; @@ -608,7 +608,7 @@ void R_DrawSurface (void) (*pblockdrawer)(); - soffset = soffset + horzblockstep; + soffset = soffset + blocksize; if (soffset >= smax) soffset = 0; From a6572dd0422b23f067f9372cf99116b38bb6f715 Mon Sep 17 00:00:00 2001 From: mittorn Date: Mon, 15 Apr 2019 04:59:05 +0700 Subject: [PATCH 086/115] ref_soft: fix crash on map restart again --- r_main.c | 2 -- r_surf.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/r_main.c b/r_main.c index f1103a4d..0873684c 100644 --- a/r_main.c +++ b/r_main.c @@ -1840,8 +1840,6 @@ void GAME_EXPORT R_NewMap (void) R_ClearDecals(); // clear all level decals R_StudioResetPlayerModels(); - D_FlushCaches(); - r_cnumsurfs = sw_maxsurfs->value; if (r_cnumsurfs <= MINSURFACES) diff --git a/r_surf.c b/r_surf.c index a16256dc..954e3b3b 100644 --- a/r_surf.c +++ b/r_surf.c @@ -1010,7 +1010,7 @@ void D_FlushCaches( void ) qboolean newmap = !world || !Q_strcmp( tr.mapname, WORLDMODEL->name ); // if newmap, surfaces already freed - if( !newmap && !tr.map_unload ) + if( !tr.map_unload ) { for(c = sc_base ; c ; c = c->next ) { From 37ee9752e114e1ac7f37b55d94fcc58537788cb8 Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 17 Apr 2019 06:11:11 +0700 Subject: [PATCH 087/115] ref_soft: Update ref interface --- r_beams.c | 4 +- r_context.c | 76 +++++++++++--------------------- r_image.c | 8 ++-- r_local.h | 1 + r_main.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++++++- r_studio.c | 4 +- 6 files changed, 158 insertions(+), 60 deletions(-) diff --git a/r_beams.c b/r_beams.c index 166b71a0..d6648f40 100644 --- a/r_beams.c +++ b/r_beams.c @@ -1082,7 +1082,7 @@ void R_BeamDraw( BEAM *pbeam, float frametime ) // XASH SPECIFIC: get brightness from head entity pStart = gEngfuncs.R_BeamGetEntity( pbeam->startEntity ); if( pStart && pStart->curstate.rendermode != kRenderNormal ) - pbeam->brightness = gEngfuncs.CL_FxBlend( pStart ) / 255.0f; + pbeam->brightness = CL_FxBlend( pStart ) / 255.0f; } if( FBitSet( pbeam->flags, FBEAM_FADEIN )) @@ -1202,7 +1202,7 @@ void R_BeamDrawCustomEntity( cl_entity_t *ent ) { BEAM beam; float amp = ent->curstate.body / 100.0f; - float blend = gEngfuncs.CL_FxBlend( ent ) / 255.0f; + float blend = CL_FxBlend( ent ) / 255.0f; float r, g, b; int beamFlags; diff --git a/r_context.c b/r_context.c index f13b8825..5087df30 100644 --- a/r_context.c +++ b/r_context.c @@ -59,45 +59,6 @@ static const byte * GAME_EXPORT R_GetTextureOriginalBuffer( unsigned int idx ) return NULL; } -static int GAME_EXPORT R_GetBuiltinTexture( enum ref_shared_texture_e type ) -{ - switch( type ) - { - case REF_DEFAULT_TEXTURE: return tr.defaultTexture; - case REF_GRAY_TEXTURE: return tr.grayTexture; - case REF_WHITE_TEXTURE: return tr.whiteTexture; - case REF_SOLIDSKY_TEXTURE: return tr.solidskyTexture; - case REF_ALPHASKY_TEXTURE: return tr.alphaskyTexture; - default: gEngfuncs.Host_Error( "R_GetBuiltinTexture: unsupported type %d\n", type ); - } - - return 0; -} - -static void GAME_EXPORT R_FreeSharedTexture( enum ref_shared_texture_e type ) -{ - int num = 0; - - switch( type ) - { - case REF_SOLIDSKY_TEXTURE: - num = tr.solidskyTexture; - tr.solidskyTexture = 0; - break; - case REF_ALPHASKY_TEXTURE: - num = tr.alphaskyTexture; - tr.alphaskyTexture = 0; - break; - case REF_DEFAULT_TEXTURE: - case REF_GRAY_TEXTURE: - case REF_WHITE_TEXTURE: - gEngfuncs.Host_Error( "R_FreeSharedTexture: invalid type %d\n", type ); - default: gEngfuncs.Host_Error( "R_FreeSharedTexture: unsupported type %d\n", type ); - } - - GL_FreeTexture( num ); -} - /* ============= CL_FillRGBA @@ -161,7 +122,8 @@ qboolean GAME_EXPORT Mod_ProcessRenderData( model_t *mod, qboolean create, const return loaded; } -static int GAME_EXPORT GL_RenderGetParm( int parm, int arg ) + +static int GL_RefGetParm( int parm, int arg ) { image_t *glt; @@ -179,6 +141,12 @@ static int GAME_EXPORT GL_RenderGetParm( int parm, int arg ) case PARM_TEX_SRC_HEIGHT: glt = R_GetTexture( arg ); return glt->srcHeight; + case PARM_TEX_GLFORMAT: + glt = R_GetTexture( arg ); + return 0; //glt->format; + case PARM_TEX_ENCODE: + glt = R_GetTexture( arg ); + return 0; //glt->encode; case PARM_TEX_MIPCOUNT: glt = R_GetTexture( arg ); return glt->numMips; @@ -189,7 +157,7 @@ static int GAME_EXPORT GL_RenderGetParm( int parm, int arg ) Assert( arg >= 0 && arg < 6 ); return tr.skyboxTextures[arg]; case PARM_TEX_SKYTEXNUM: - return 0; + return 0; //tr.skytexturenum; case PARM_TEX_LIGHTMAP: arg = bound( 0, arg, MAX_LIGHTMAPS - 1 ); return tr.lightmapTextures[arg]; @@ -201,20 +169,34 @@ static int GAME_EXPORT GL_RenderGetParm( int parm, int arg ) return gpGlobals->width; case PARM_SCREEN_HEIGHT: return gpGlobals->height; + case PARM_TEX_TARGET: + glt = R_GetTexture( arg ); + return 0; //glt->target; + case PARM_TEX_TEXNUM: + glt = R_GetTexture( arg ); + return 0; //glt->texnum; case PARM_TEX_FLAGS: glt = R_GetTexture( arg ); return glt->flags; + case PARM_ACTIVE_TMU: + return 0; //glState.activeTMU; case PARM_LIGHTSTYLEVALUE: arg = bound( 0, arg, MAX_LIGHTSTYLES - 1 ); return tr.lightstylevalue[arg]; case PARM_MAX_IMAGE_UNITS: - return 1; + return 0; //GL_MaxTextureUnits(); case PARM_REBUILD_GAMMA: - return 0;//glConfig.softwareGammaUpdate; + return 0; //glConfig.softwareGammaUpdate; case PARM_SURF_SAMPLESIZE: if( arg >= 0 && arg < WORLDMODEL->numsurfaces ) return gEngfuncs.Mod_SampleSizeForFace( &WORLDMODEL->surfaces[arg] ); return LM_SAMPLE_SIZE; + case PARM_GL_CONTEXT_TYPE: + return 0; //glConfig.context; + case PARM_GLES_WRAPPER: + return 0; //glConfig.wrapper; + case PARM_STENCIL_ACTIVE: + return 0; //glState.stencilEnabled; case PARM_SKY_SPHERE: return ENGINE_GET_PARM_( parm, arg ) && !tr.fCustomSkybox; default: @@ -495,16 +477,11 @@ ref_interface_t gReffuncs = CL_AddCustomBeam, R_ProcessEntData, - IsNormalPass, - R_ShowTextures, R_ShowTree, - R_IncrementSpeedsCounter, R_GetTextureOriginalBuffer, GL_LoadTextureFromBuffer, - R_GetBuiltinTexture, - R_FreeSharedTexture, GL_ProcessTexture, R_SetupSky, @@ -545,7 +522,7 @@ ref_interface_t gReffuncs = CL_DrawBeams, R_BeamCull, - GL_RenderGetParm, + GL_RefGetParm, R_GetDetailScaleForTexture, R_GetExtraParmsForTexture, R_GetFrameTime, @@ -585,7 +562,6 @@ ref_interface_t gReffuncs = R_StudioGetTexture, R_RenderFrame, - GL_BuildLightmaps, Mod_SetOrthoBounds, R_SpeedsMessage, Mod_GetCurrentVis, diff --git a/r_image.c b/r_image.c index e38b9353..90e9e6e6 100644 --- a/r_image.c +++ b/r_image.c @@ -1281,7 +1281,7 @@ static void GL_CreateInternalTextures( void ) } } - tr.defaultTexture = GL_LoadTextureInternal( "*default", pic, TF_COLORMAP ); + tr.defaultTexture = GL_LoadTextureInternal( REF_DEFAULT_TEXTURE, pic, TF_COLORMAP ); // particle texture from quake1 pic = GL_FakeImage( 16, 16, 1, IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA ); @@ -1305,19 +1305,19 @@ static void GL_CreateInternalTextures( void ) pic = GL_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR ); for( x = 0; x < 16; x++ ) ((uint *)pic->buffer)[x] = 0xFFFFFFFF; - tr.whiteTexture = GL_LoadTextureInternal( "*white", pic, TF_COLORMAP ); + tr.whiteTexture = GL_LoadTextureInternal( REF_WHITE_TEXTURE, pic, TF_COLORMAP ); // gray texture pic = GL_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR ); for( x = 0; x < 16; x++ ) ((uint *)pic->buffer)[x] = 0xFF7F7F7F; - tr.grayTexture = GL_LoadTextureInternal( "*gray", pic, TF_COLORMAP ); + tr.grayTexture = GL_LoadTextureInternal( REF_GRAY_TEXTURE, pic, TF_COLORMAP ); // black texture pic = GL_FakeImage( 4, 4, 1, IMAGE_HAS_COLOR ); for( x = 0; x < 16; x++ ) ((uint *)pic->buffer)[x] = 0xFF000000; - tr.blackTexture = GL_LoadTextureInternal( "*black", pic, TF_COLORMAP ); + tr.blackTexture = GL_LoadTextureInternal( REF_BLACK_TEXTURE, pic, TF_COLORMAP ); // cinematic dummy pic = GL_FakeImage( 640, 100, 1, IMAGE_HAS_COLOR ); diff --git a/r_local.h b/r_local.h index dc6e7acf..14e0c2db 100644 --- a/r_local.h +++ b/r_local.h @@ -1279,6 +1279,7 @@ void R_RenderTriangle( finalvert_t *fv1 , finalvert_t *fv2, finalvert_t *fv3 ); void R_SetupFinalVert( finalvert_t *fv, float x, float y, float z, int light, int s, int t ); void RotatedBBox (vec3_t mins, vec3_t maxs, vec3_t angles, vec3_t tmins, vec3_t tmaxs); int R_BmodelCheckBBox (float *minmaxs); +int CL_FxBlend( cl_entity_t *e ); void R_SetUpWorldTransform (void); diff --git a/r_main.c b/r_main.c index 0873684c..4e1fa427 100644 --- a/r_main.c +++ b/r_main.c @@ -367,7 +367,7 @@ qboolean GAME_EXPORT R_AddEntity( struct cl_entity_s *clent, int type ) if( FBitSet( clent->curstate.effects, EF_NODRAW )) return false; // done - if( !R_ModelOpaque( clent->curstate.rendermode ) && gEngfuncs.CL_FxBlend( clent ) <= 0 ) + if( !R_ModelOpaque( clent->curstate.rendermode ) && CL_FxBlend( clent ) <= 0 ) return true; // invisible if( type == ET_FRAGMENTED ) @@ -909,7 +909,7 @@ void R_DrawEntitiesOnList( void ) // handle studiomodels with custom rendermodes on texture if( RI.currententity->curstate.rendermode != kRenderNormal ) - tr.blend = gEngfuncs.CL_FxBlend( RI.currententity ) / 255.0f; + tr.blend = CL_FxBlend( RI.currententity ) / 255.0f; else tr.blend = 1.0f; // draw as solid but sorted by distance if( tr.blend <= 0.0f ) continue; @@ -2004,3 +2004,124 @@ void GAME_EXPORT R_Shutdown() gEngfuncs.R_Free_Video(); } + +/* +=============== +CL_FxBlend +=============== +*/ +int CL_FxBlend( cl_entity_t *e ) +{ + int blend = 0; + float offset, dist; + vec3_t tmp; + + offset = ((int)e->index ) * 363.0f; // Use ent index to de-sync these fx + + switch( e->curstate.renderfx ) + { + case kRenderFxPulseSlowWide: + blend = e->curstate.renderamt + 0x40 * sin( gpGlobals->time * 2 + offset ); + break; + case kRenderFxPulseFastWide: + blend = e->curstate.renderamt + 0x40 * sin( gpGlobals->time * 8 + offset ); + break; + case kRenderFxPulseSlow: + blend = e->curstate.renderamt + 0x10 * sin( gpGlobals->time * 2 + offset ); + break; + case kRenderFxPulseFast: + blend = e->curstate.renderamt + 0x10 * sin( gpGlobals->time * 8 + offset ); + break; + case kRenderFxFadeSlow: + if( RP_NORMALPASS( )) + { + if( e->curstate.renderamt > 0 ) + e->curstate.renderamt -= 1; + else e->curstate.renderamt = 0; + } + blend = e->curstate.renderamt; + break; + case kRenderFxFadeFast: + if( RP_NORMALPASS( )) + { + if( e->curstate.renderamt > 3 ) + e->curstate.renderamt -= 4; + else e->curstate.renderamt = 0; + } + blend = e->curstate.renderamt; + break; + case kRenderFxSolidSlow: + if( RP_NORMALPASS( )) + { + if( e->curstate.renderamt < 255 ) + e->curstate.renderamt += 1; + else e->curstate.renderamt = 255; + } + blend = e->curstate.renderamt; + break; + case kRenderFxSolidFast: + if( RP_NORMALPASS( )) + { + if( e->curstate.renderamt < 252 ) + e->curstate.renderamt += 4; + else e->curstate.renderamt = 255; + } + blend = e->curstate.renderamt; + break; + case kRenderFxStrobeSlow: + blend = 20 * sin( gpGlobals->time * 4 + offset ); + if( blend < 0 ) blend = 0; + else blend = e->curstate.renderamt; + break; + case kRenderFxStrobeFast: + blend = 20 * sin( gpGlobals->time * 16 + offset ); + if( blend < 0 ) blend = 0; + else blend = e->curstate.renderamt; + break; + case kRenderFxStrobeFaster: + blend = 20 * sin( gpGlobals->time * 36 + offset ); + if( blend < 0 ) blend = 0; + else blend = e->curstate.renderamt; + break; + case kRenderFxFlickerSlow: + blend = 20 * (sin( gpGlobals->time * 2 ) + sin( gpGlobals->time * 17 + offset )); + if( blend < 0 ) blend = 0; + else blend = e->curstate.renderamt; + break; + case kRenderFxFlickerFast: + blend = 20 * (sin( gpGlobals->time * 16 ) + sin( gpGlobals->time * 23 + offset )); + if( blend < 0 ) blend = 0; + else blend = e->curstate.renderamt; + break; + case kRenderFxHologram: + case kRenderFxDistort: + VectorCopy( e->origin, tmp ); + VectorSubtract( tmp, RI.vieworg, tmp ); + dist = DotProduct( tmp, RI.vforward ); + + // turn off distance fade + if( e->curstate.renderfx == kRenderFxDistort ) + dist = 1; + + if( dist <= 0 ) + { + blend = 0; + } + else + { + e->curstate.renderamt = 180; + if( dist <= 100 ) blend = e->curstate.renderamt; + else blend = (int) ((1.0f - ( dist - 100 ) * ( 1.0f / 400.0f )) * e->curstate.renderamt ); + blend += gEngfuncs.COM_RandomLong( -32, 31 ); + } + break; + default: + blend = e->curstate.renderamt; + break; + } + + blend = bound( 0, blend, 255 ); + + return blend; +} + diff --git a/r_studio.c b/r_studio.c index 0a69142e..7a153302 100644 --- a/r_studio.c +++ b/r_studio.c @@ -1862,7 +1862,7 @@ void R_StudioSetRenderamt( int iRenderamt ) if( !RI.currententity ) return; RI.currententity->curstate.renderamt = iRenderamt; - tr.blend = gEngfuncs.CL_FxBlend( RI.currententity ) / 255.0f; + tr.blend = CL_FxBlend( RI.currententity ) / 255.0f; } /* @@ -3466,7 +3466,7 @@ void R_DrawViewModel( void ) if( !RP_NORMALPASS() || ENGINE_GET_PARM( PARM_LOCAL_HEALTH ) <= 0 || !CL_IsViewEntityLocalPlayer()) return; - tr.blend = gEngfuncs.CL_FxBlend( view ) / 255.0f; + tr.blend = CL_FxBlend( view ) / 255.0f; if( !R_ModelOpaque( view->curstate.rendermode ) && tr.blend <= 0.0f ) return; // invisible ? From fbef500fb334cc47a5ff665377d4ceb6016d221e Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 17 Apr 2019 06:15:24 +0700 Subject: [PATCH 088/115] ref_soft: Fix division by zero --- r_surf.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/r_surf.c b/r_surf.c index 954e3b3b..909370b2 100644 --- a/r_surf.c +++ b/r_surf.c @@ -1198,6 +1198,9 @@ void R_DrawSurfaceDecals() w = w >> r_drawsurf.surfmip; h = h >> r_drawsurf.surfmip; + if( w < 1 || h < 1 ) + continue; + if( x < 0 ) { s1 += (-x)*(s2-s1) / w; From 103077b68694b329f11a329873dd768c5225cf44 Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 17 Apr 2019 06:34:01 +0700 Subject: [PATCH 089/115] ref_soft: clean unused variables --- r_context.c | 2 +- r_local.h | 1 - r_main.c | 13 +++++-------- r_surf.c | 4 ---- 4 files changed, 6 insertions(+), 14 deletions(-) diff --git a/r_context.c b/r_context.c index 5087df30..e33a9d6e 100644 --- a/r_context.c +++ b/r_context.c @@ -186,7 +186,7 @@ static int GL_RefGetParm( int parm, int arg ) case PARM_MAX_IMAGE_UNITS: return 0; //GL_MaxTextureUnits(); case PARM_REBUILD_GAMMA: - return 0; //glConfig.softwareGammaUpdate; + return 0; case PARM_SURF_SAMPLESIZE: if( arg >= 0 && arg < WORLDMODEL->numsurfaces ) return gEngfuncs.Mod_SampleSizeForFace( &WORLDMODEL->surfaces[arg] ); diff --git a/r_local.h b/r_local.h index 14e0c2db..43714d96 100644 --- a/r_local.h +++ b/r_local.h @@ -293,7 +293,6 @@ typedef struct vec3_t modelorg; // relative to viewpoint qboolean fCustomSkybox; - char mapname[MAX_STRING]; int sample_size; uint sample_bits; qboolean map_unload; diff --git a/r_main.c b/r_main.c index 4e1fa427..c4d1f892 100644 --- a/r_main.c +++ b/r_main.c @@ -1670,26 +1670,23 @@ R_BeginFrame */ void GAME_EXPORT R_BeginFrame( qboolean clearScene ) { - +#if 0 // unused if( R_DoResetGamma( )) { gEngfuncs.BuildGammaTable( 1.8f, 0.0f ); - // glConfig.softwareGammaUpdate = true; - // GL_RebuildLightmaps(); - // glConfig.softwareGammaUpdate = false; D_FlushCaches( ); // next frame will be restored gamma SetBits( vid_brightness->flags, FCVAR_CHANGED ); SetBits( vid_gamma->flags, FCVAR_CHANGED ); } - else if( FBitSet( vid_gamma->flags, FCVAR_CHANGED ) || FBitSet( vid_brightness->flags, FCVAR_CHANGED )) + else +#endif + if( FBitSet( vid_gamma->flags, FCVAR_CHANGED ) || FBitSet( vid_brightness->flags, FCVAR_CHANGED )) { gEngfuncs.BuildGammaTable( vid_gamma->value, vid_brightness->value ); - //glConfig.softwareGammaUpdate = true; - // GL_RebuildLightmaps(); + D_FlushCaches( ); - //glConfig.softwareGammaUpdate = false; // next frame will be restored gamma ClearBits( vid_brightness->flags, FCVAR_CHANGED ); ClearBits( vid_gamma->flags, FCVAR_CHANGED ); diff --git a/r_surf.c b/r_surf.c index 909370b2..a5fb484d 100644 --- a/r_surf.c +++ b/r_surf.c @@ -1006,8 +1006,6 @@ D_FlushCaches void D_FlushCaches( void ) { surfcache_t *c; - model_t *world = WORLDMODEL; - qboolean newmap = !world || !Q_strcmp( tr.mapname, WORLDMODEL->name ); // if newmap, surfaces already freed if( !tr.map_unload ) @@ -1018,8 +1016,6 @@ void D_FlushCaches( void ) *c->owner = NULL; } } - else - Q_strncpy( tr.mapname, WORLDMODEL->name, MAX_STRING ); sc_rover = sc_base; sc_base->next = NULL; From 7663da80c3256e0800dc803cd63f4171cc4caa31 Mon Sep 17 00:00:00 2001 From: mittorn Date: Wed, 17 Apr 2019 07:17:43 +0700 Subject: [PATCH 090/115] ref_soft: Setup viewport --- r_misc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/r_misc.c b/r_misc.c index 7d02bb48..e3c00f72 100644 --- a/r_misc.c +++ b/r_misc.c @@ -340,10 +340,14 @@ void R_SetupFrameQ (void) // r_dowarp = true; // else - vrect.x = 0;//r_newrefdef.x; + /*vrect.x = 0;//r_newrefdef.x; vrect.y = 0;//r_newrefdef.y; vrect.width = gpGlobals->width; - vrect.height = gpGlobals->height; + vrect.height = gpGlobals->height;*/ + vrect.x = RI.viewport[0]; + vrect.y = RI.viewport[1]; + vrect.width = RI.viewport[2]; + vrect.height = RI.viewport[3]; d_viewbuffer = (void *)vid.buffer; r_screenwidth = vid.rowbytes; From fd962869e64eb4c465586d266189e2baf37246a2 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sun, 12 May 2019 18:05:03 +0300 Subject: [PATCH 091/115] ref_soft: update to latest API version --- r_context.c | 10 ++-------- r_local.h | 2 +- r_main.c | 10 +++++----- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/r_context.c b/r_context.c index e33a9d6e..e219d62c 100644 --- a/r_context.c +++ b/r_context.c @@ -314,12 +314,6 @@ void GAME_EXPORT GL_SetTexCoordArrayMode() } -void GAME_EXPORT GL_OnContextCreated() -{ - //R_InitBlit(); - -} - void GAME_EXPORT GL_InitExtensions() { @@ -364,12 +358,13 @@ void GAME_EXPORT R_SetupSky(const char *skyboxname) qboolean GAME_EXPORT VID_ScreenShot(const char *filename, int shot_type) { - + return false; } qboolean GAME_EXPORT VID_CubemapShot(const char *base, uint size, const float *vieworg, qboolean skyshot) { // cubemaps? in my softrender??? + return false; } void R_InitSkyClouds(mip_t *mt, texture_t *tx, qboolean custom_palette) @@ -457,7 +452,6 @@ ref_interface_t gReffuncs = R_Shutdown, GL_SetupAttributes, - GL_OnContextCreated, GL_InitExtensions, GL_ClearExtensions, diff --git a/r_local.h b/r_local.h index 43714d96..4d1ba92f 100644 --- a/r_local.h +++ b/r_local.h @@ -613,7 +613,7 @@ void GL_FreeImage( const char *name ); qboolean VID_ScreenShot( const char *filename, int shot_type ); qboolean VID_CubemapShot( const char *base, uint size, const float *vieworg, qboolean skyshot ); void R_BeginFrame( qboolean clearScene ); -int R_RenderFrame( const struct ref_viewpass_s *vp ); +void R_RenderFrame( const struct ref_viewpass_s *vp ); void R_EndFrame( void ); void R_ClearScene( void ); void R_GetTextureParms( int *w, int *h, int texnum ); diff --git a/r_main.c b/r_main.c index c4d1f892..538cdc66 100644 --- a/r_main.c +++ b/r_main.c @@ -1741,14 +1741,14 @@ void R_SetupRefParams( const ref_viewpass_t *rvp ) R_RenderFrame =============== */ -int GAME_EXPORT R_RenderFrame( const ref_viewpass_t *rvp ) +void GAME_EXPORT R_RenderFrame( const ref_viewpass_t *rvp ) { if( r_norefresh->value ) - return 1; + return; // prevent cache overrun if( gpGlobals->height > vid.height || gpGlobals->width > vid.width ) - return 1; + return; // setup the initial render params R_SetupRefParams( rvp ); @@ -1763,7 +1763,7 @@ int GAME_EXPORT R_RenderFrame( const ref_viewpass_t *rvp ) //R_GatherPlayerLight(); tr.realframecount++; tr.fResetVis = true; - return 1; + return; } } @@ -1774,7 +1774,7 @@ int GAME_EXPORT R_RenderFrame( const ref_viewpass_t *rvp ) tr.realframecount++; // right called after viewmodel events R_RenderScene(); - return 1; + return; } /* From 9c4a0d2397d9343fef7322d6acbe6781f3989274 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Thu, 10 Oct 2019 05:03:37 +0300 Subject: [PATCH 092/115] ref_soft: context: upgrade to latest RefAPI --- r_context.c | 12 +++++++++++- r_image.c | 6 +++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/r_context.c b/r_context.c index e219d62c..da1fe085 100644 --- a/r_context.c +++ b/r_context.c @@ -446,10 +446,16 @@ void GAME_EXPORT GL_SetupAttributes( int safegl ) gEngfuncs.GL_SetAttribute( REF_GL_BLUE_SIZE, 5 ); } +const char *R_GetConfigName( void ) +{ + return "ref_soft"; // software specific cvars will go to ref_soft.cfg +} + ref_interface_t gReffuncs = { R_Init, R_Shutdown, + R_GetConfigName, GL_SetupAttributes, GL_InitExtensions, @@ -472,7 +478,6 @@ ref_interface_t gReffuncs = R_ProcessEntData, R_ShowTextures, - R_ShowTree, R_GetTextureOriginalBuffer, GL_LoadTextureFromBuffer, @@ -604,3 +609,8 @@ int EXPORT GAME_EXPORT GetRefAPI( int version, ref_interface_t *funcs, ref_api_t return REF_API_VERSION; } + +void EXPORT GetRefHumanReadableName( char *out, size_t size ) +{ + Q_strncpy( out, "Software", size ); +} diff --git a/r_image.c b/r_image.c index 90e9e6e6..c512a07a 100644 --- a/r_image.c +++ b/r_image.c @@ -829,7 +829,7 @@ static image_t *GL_TextureForName( const char *name ) uint hash; // find the texture in array - hash = gEngfuncs.COM_HashKey( name, TEXTURES_HASH_SIZE ); + hash = COM_HashKey( name, TEXTURES_HASH_SIZE ); for( tex = r_imagesHashTable[hash]; tex != NULL; tex = tex->nextHash ) { @@ -870,7 +870,7 @@ static image_t *GL_AllocTexture( const char *name, texFlags_t flags ) tex->flags = flags; // add to hash table - tex->hashValue = gEngfuncs.COM_HashKey( name, TEXTURES_HASH_SIZE ); + tex->hashValue = COM_HashKey( name, TEXTURES_HASH_SIZE ); tex->nextHash = r_imagesHashTable[tex->hashValue]; r_imagesHashTable[tex->hashValue] = tex; @@ -1380,7 +1380,7 @@ void R_InitImages( void ) // create unused 0-entry Q_strncpy( r_images->name, "*unused*", sizeof( r_images->name )); - r_images->hashValue = gEngfuncs.COM_HashKey( r_images->name, TEXTURES_HASH_SIZE ); + r_images->hashValue = COM_HashKey( r_images->name, TEXTURES_HASH_SIZE ); r_images->nextHash = r_imagesHashTable[r_images->hashValue]; r_imagesHashTable[r_images->hashValue] = r_images; r_numImages = 1; From 690a317f4f83e0be8eb02806d9feb5274ca96dfd Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Thu, 10 Oct 2019 05:28:08 +0300 Subject: [PATCH 093/115] ref_soft: fix style errors --- r_context.c | 20 ++++++++++---------- r_glblit.c | 14 +++++++------- r_main.c | 20 +++++++++++--------- r_studio.c | 12 ++++++------ 4 files changed, 34 insertions(+), 32 deletions(-) diff --git a/r_context.c b/r_context.c index da1fe085..38aff2bc 100644 --- a/r_context.c +++ b/r_context.c @@ -309,26 +309,26 @@ void GAME_EXPORT R_ProcessEntData( qboolean allocate ) // stubs -void GAME_EXPORT GL_SetTexCoordArrayMode() +void GAME_EXPORT GL_SetTexCoordArrayMode( void ) { } -void GAME_EXPORT GL_InitExtensions() +void GAME_EXPORT GL_InitExtensions( void ) { } -void GAME_EXPORT GL_ClearExtensions() +void GAME_EXPORT GL_ClearExtensions( void ) { } -void GAME_EXPORT GL_BackendStartFrame() +void GAME_EXPORT GL_BackendStartFrame( void ) { } -void GAME_EXPORT GL_BackendEndFrame() +void GAME_EXPORT GL_BackendEndFrame( void ) { } @@ -341,12 +341,12 @@ void GAME_EXPORT GL_SetRenderMode(int mode) /// maybe, setup block drawing function pointers here } -void GAME_EXPORT R_ShowTextures() +void GAME_EXPORT R_ShowTextures( void ) { // textures undone too } -void GAME_EXPORT R_ShowTree() +void GAME_EXPORT R_ShowTree( void ) { // do we really need this here??? } @@ -392,7 +392,7 @@ void GAME_EXPORT GL_LoadTexMatrixExt(const float *glmatrix) } -void GAME_EXPORT GL_LoadIdentityTexMatrix() +void GAME_EXPORT GL_LoadIdentityTexMatrix( void ) { } @@ -412,7 +412,7 @@ void GAME_EXPORT GL_TextureTarget(uint target) } -void GAME_EXPORT GL_BuildLightmaps() +void GAME_EXPORT GL_BuildLightmaps( void ) { CL_RunLightStyles(); } @@ -427,7 +427,7 @@ qboolean GAME_EXPORT R_SpeedsMessage(char *out, size_t size) return false; } -byte *GAME_EXPORT Mod_GetCurrentVis() +byte *GAME_EXPORT Mod_GetCurrentVis( void ) { return NULL; } diff --git a/r_glblit.c b/r_glblit.c index a73cac59..1f0ccc59 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -129,7 +129,7 @@ void R_BuildScreenMap( void ) #define FOR_EACH_COLOR(x) for( r##x = 0; r##x < BIT(3); r##x++ ) for( g##x = 0; g##x < BIT(3); g##x++ ) for( b##x = 0; b##x < BIT(2); b##x++ ) -void R_BuildBlendMaps() +void R_BuildBlendMaps( void ) { unsigned int r1, g1, b1; unsigned int r2, g2, b2; @@ -176,6 +176,7 @@ void R_BuildBlendMaps() uint color = i << 3; uint m = color >> 8; uint j = color & 0xff; + unsigned short index1 = i; r1 = ((m >> (8 - 3) )<< 2 ) & MASK(5); g1 = ((m >> (8 - 3 - 3)) << 3) & MASK(6); @@ -185,7 +186,6 @@ void R_BuildBlendMaps() b1 |= MOVE_BIT(j, 6, 2) | MOVE_BIT(j, 3, 1) | MOVE_BIT(j, 0, 0); - unsigned short index1 = i; for( j = 0; j < 32; j++) { unsigned int index2 = j << 13; @@ -208,6 +208,7 @@ void R_BuildBlendMaps() uint color = i << 6 | BIT(5) | BIT(4) | BIT(3); uint m = color >> 8; uint j = color & 0xff; + unsigned short index1 = i; r1 = ((m >> (8 - 3) )<< 2 ) & MASK(5); g1 = ((m >> (8 - 3 - 3)) << 3) & MASK(6); @@ -217,7 +218,6 @@ void R_BuildBlendMaps() b1 |= MOVE_BIT(j, 6, 2) | MOVE_BIT(j, 3, 1) | MOVE_BIT(j, 0, 0); - unsigned short index1 = i; FOR_EACH_COLOR(2) { unsigned int index2 = (r2 << (2 + 3) | g2 << 2 | b2) << 10; @@ -254,9 +254,9 @@ void R_BuildBlendMaps() #endif } -void R_AllocScreen(); +void R_AllocScreen( void ); -void R_InitBlit() +void R_InitBlit(void) { /*LOAD(glBegin); @@ -296,7 +296,7 @@ void R_InitBlit() R_AllocScreen(); } -void R_AllocScreen() +void R_AllocScreen( void ) { if( gpGlobals->width < 320 ) gpGlobals->width = 320; @@ -319,7 +319,7 @@ void R_AllocScreen() vid.buffer = Mem_Malloc( r_temppool, vid.width * vid.height*sizeof( pixel_t ) ); } -void R_BlitScreen() +void R_BlitScreen( void ) { //memset( vid.buffer, 10, vid.width * vid.height ); int u, v; diff --git a/r_main.c b/r_main.c index 538cdc66..493914c5 100644 --- a/r_main.c +++ b/r_main.c @@ -208,7 +208,7 @@ static int R_TransEntityCompare( const cl_entity_t **a, const cl_entity_t **b ) rendermode2 = R_GetEntityRenderMode( ent2 ); // sort by distance - if( ent1->model && ent1->model->type != mod_brush || rendermode1 != kRenderTransAlpha ) + if( ( ent1->model && ent1->model->type != mod_brush ) || rendermode1 != kRenderTransAlpha ) { VectorAverage( ent1->model->mins, ent1->model->maxs, org ); VectorAdd( ent1->origin, org, org ); @@ -217,7 +217,7 @@ static int R_TransEntityCompare( const cl_entity_t **a, const cl_entity_t **b ) } else dist1 = 1000000000; - if( ent1->model && ent2->model->type != mod_brush || rendermode2 != kRenderTransAlpha ) + if( ( ent1->model && ent2->model->type != mod_brush ) || rendermode2 != kRenderTransAlpha ) { VectorAverage( ent2->model->mins, ent2->model->maxs, org ); VectorAdd( ent2->origin, org, org ); @@ -795,6 +795,10 @@ static image_t *R_RecursiveFindWaterTexture( const mnode_t *node, const mnode_t return NULL; } +extern void R_PolysetFillSpans8 ( void * ); +extern void R_PolysetDrawSpansConstant8_33( void *pspanpackage); +extern void R_PolysetDrawSpans8_33( void *pspanpackage); + /* ============= R_DrawEntitiesOnList @@ -802,16 +806,13 @@ R_DrawEntitiesOnList */ void R_DrawEntitiesOnList( void ) { + extern void (*d_pdrawspans)(void *); int i; //extern int d_aflatcolor; //d_aflatcolor = 0; tr.blend = 1.0f; // GL_CheckForErrors(); //RI.currententity = gEngfuncs.GetEntityByIndex(0); - extern void (*d_pdrawspans)(void *); - extern void R_PolysetFillSpans8 ( void * ); - extern void R_PolysetDrawSpansConstant8_33( void *pspanpackage); - extern void R_PolysetDrawSpans8_33( void *pspanpackage); d_pdrawspans = R_PolysetFillSpans8; GL_SetRenderMode(kRenderNormal); // first draw solid entities @@ -1826,9 +1827,10 @@ R_NewMap void GAME_EXPORT R_NewMap (void) { int i; - r_viewcluster = -1; model_t *world = WORLDMODEL; + r_viewcluster = -1; + tr.draw_list->num_solid_entities = 0; tr.draw_list->num_trans_entities = 0; tr.draw_list->num_beam_entities = 0; @@ -1921,7 +1923,7 @@ void R_InitTurb (void) -qboolean GAME_EXPORT R_Init() +qboolean GAME_EXPORT R_Init( void ) { gl_emboss_scale = gEngfuncs.Cvar_Get( "gl_emboss_scale", "0", FCVAR_ARCHIVE|FCVAR_LATCH, "fake bumpmapping scale" ); vid_gamma = gEngfuncs.pfnGetCvarPointer( "gamma", 0 ); @@ -1995,7 +1997,7 @@ qboolean GAME_EXPORT R_Init() return true; } -void GAME_EXPORT R_Shutdown() +void GAME_EXPORT R_Shutdown( void ) { R_ShutdownImages(); gEngfuncs.R_Free_Video(); diff --git a/r_studio.c b/r_studio.c index 7a153302..d51e6947 100644 --- a/r_studio.c +++ b/r_studio.c @@ -1124,7 +1124,7 @@ void R_StudioBuildNormalTable( void ) pmesh = (mstudiomesh_t *)((byte *)m_pStudioHeader + m_pSubModel->meshindex) + j; ptricmds = (short *)((byte *)m_pStudioHeader + pmesh->triindex); - while( i = *( ptricmds++ )) + while(( i = *( ptricmds++ ))) { if( i < 0 ) i = -i; @@ -1172,7 +1172,7 @@ void R_StudioGenerateNormals( void ) pmesh = (mstudiomesh_t *)((byte *)m_pStudioHeader + m_pSubModel->meshindex) + j; ptricmds = (short *)((byte *)m_pStudioHeader + pmesh->triindex); - while( i = *( ptricmds++ )) + while(( i = *( ptricmds++ ))) { if( i < 0 ) { @@ -1939,7 +1939,7 @@ _inline void R_StudioDrawNormalMesh( short *ptricmds, vec3_t *pstudionorms, floa float *lv; int i; - while( i = *( ptricmds++ )) + while(( i = *( ptricmds++ ))) { if( i < 0 ) { @@ -1972,7 +1972,7 @@ _inline void R_StudioDrawFloatMesh( short *ptricmds, vec3_t *pstudionorms ) float *lv; int i; - while( i = *( ptricmds++ )) + while(( i = *( ptricmds++ ))) { if( i < 0 ) { @@ -2006,7 +2006,7 @@ _inline void R_StudioDrawChromeMesh( short *ptricmds, vec3_t *pstudionorms, floa qboolean glowShell = (scale > 0.0f) ? true : false; vec3_t vert; - while( i = *( ptricmds++ )) + while(( i = *( ptricmds++ ))) { if( i < 0 ) { @@ -2746,7 +2746,7 @@ static void R_StudioDrawPointsShadow( void ) r_stats.c_studio_polys += pmesh->numtris; - while( i = *( ptricmds++ )) + while(( i = *( ptricmds++ ))) { if( i < 0 ) { From d96dcfba592a15fedd53c6cf252e3d26ebfa86ec Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Thu, 10 Oct 2019 05:55:44 +0300 Subject: [PATCH 094/115] ref_soft: fix different warnings --- r_draw.c | 8 ++++---- r_image.c | 2 +- r_local.h | 14 +++++++------- r_polyse.c | 4 ++-- r_surf.c | 10 +++++----- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/r_draw.c b/r_draw.c index ef5adea3..3525e6b2 100644 --- a/r_draw.c +++ b/r_draw.c @@ -151,7 +151,7 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, if( transparent ) { - alpha &= src >> 16 - 3; + alpha &= src >> ( 16 - 3 ); src = src << 3; } @@ -159,12 +159,12 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, continue; if( vid.color != COLOR_WHITE ) - src = vid.modmap[src & 0xff00|(vid.color>>8)] << 8 | (src & vid.color & 0xff) | ((src & 0xff) >> 3); + src = vid.modmap[(src & 0xff00)|(vid.color>>8)] << 8 | (src & vid.color & 0xff) | ((src & 0xff) >> 3); if( vid.rendermode == kRenderTransAdd) { pixel_t screen = dest[u]; - dest[u] = vid.addmap[src & 0xff00|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 0); + dest[u] = vid.addmap[(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 0); } else if( alpha < 7) // && (vid.rendermode == kRenderTransAlpha || vid.rendermode == kRenderTransTexture ) ) { @@ -259,7 +259,7 @@ void Draw_Fill (int x, int y, int w, int h) if( vid.rendermode == kRenderTransAdd) { pixel_t screen = dest[u]; - dest[u] = vid.addmap[src & 0xff00|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 0); + dest[u] = vid.addmap[(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 0); } else if( alpha < 7) // && (vid.rendermode == kRenderTransAlpha || vid.rendermode == kRenderTransTexture ) ) { diff --git a/r_image.c b/r_image.c index c512a07a..568fbbc9 100644 --- a/r_image.c +++ b/r_image.c @@ -553,7 +553,7 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) mipCount = 4;//GL_CalcMipmapCount( tex, ( buf != NULL )); // NOTE: only single uncompressed textures can be resamples, no mips, no layers, no sides - if(( tex->depth == 1 ) && ( pic->width != tex->width ) || ( pic->height != tex->height )) + if(( tex->depth == 1 ) && (( pic->width != tex->width ) || ( pic->height != tex->height ))) data = GL_ResampleTexture( buf, pic->width, pic->height, tex->width, tex->height, normalMap ); else data = buf; diff --git a/r_local.h b/r_local.h index 4d1ba92f..6b36d4fa 100644 --- a/r_local.h +++ b/r_local.h @@ -604,7 +604,6 @@ int VGUI_GenerateTexture( void ); qboolean R_Init( void ); void R_Shutdown( void ); void GL_SetupAttributes( int safegl ); -void GL_OnContextCreated( void ); void GL_InitExtensions( void ); void GL_ClearExtensions( void ); void VID_CheckChanges( void ); @@ -1235,8 +1234,8 @@ void R_DrawBrushModel(cl_entity_t *pent); // r_blitscreen.c // void R_InitCaches (void); -void R_BlitScreen(); -void R_InitBlit(); +void R_BlitScreen( void ); +void R_InitBlit( void ); // // r_edge.c @@ -1283,10 +1282,10 @@ int CL_FxBlend( cl_entity_t *e ); void R_SetUpWorldTransform (void); -#define BLEND_ALPHA_LOW(alpha, src, screen) (vid.alphamap[(alpha << 18) |( (src & 0xff00) << 2) | (screen >> 6)] | screen & 0x3f) -#define BLEND_ALPHA(alpha, src, dst) alpha > 3?BLEND_ALPHA_LOW(7 - 1 - alpha, dst,src):BLEND_ALPHA_LOW(alpha-1, src, dst) -#define BLEND_ADD(src, screen) vid.addmap[ src& 0xff00|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 0); -#define BLEND_COLOR(src, color) vid.modmap[src & 0xff00|(color>>8)] << 8 | (src & color & 0xff) | ((src & 0xff) >> 3); +#define BLEND_ALPHA_LOW(alpha, src, screen) (vid.alphamap[((alpha) << 18) | (((src) & 0xff00) << 2) | ((screen) >> 6)] | ((screen) & 0x3f)) +#define BLEND_ALPHA(alpha, src, dst) (alpha) > 3?BLEND_ALPHA_LOW(7 - 1 - (alpha), (dst), (src)) : BLEND_ALPHA_LOW((alpha)-1, (src), (dst)) +#define BLEND_ADD(src, screen) vid.addmap[((src)& 0xff00)|((screen)>>8)] << 8 | ((screen) & 0xff) | (((src) & 0xff) >> 0); +#define BLEND_COLOR(src, color) vid.modmap[((src) & 0xff00)|((color)>>8)] << 8 | ((src) & (color) & 0xff) | (((src) & 0xff) >> 3); #define LM_SAMPLE_SIZE_AUTO(surf) (tr.sample_size == -1?gEngfuncs.Mod_SampleSizeForFace( surf ): tr.sample_size) @@ -1296,6 +1295,7 @@ void R_SetUpWorldTransform (void); // engine callbacks // #include "crtlib.h" +#include "crclib.h" #if 1 #define Mem_Malloc( pool, size ) gEngfuncs._Mem_Alloc( pool, size, false, __FILE__, __LINE__ ) #define Mem_Calloc( pool, size ) gEngfuncs._Mem_Alloc( pool, size, true, __FILE__, __LINE__ ) diff --git a/r_polyse.c b/r_polyse.c index 02c9f5f0..11a48933 100644 --- a/r_polyse.c +++ b/r_polyse.c @@ -871,9 +871,9 @@ void R_PolysetDrawSpansBlended( spanpackage_t *pspanpackage) #endif pixel_t temp = *lptex;//vid.colormap[*lptex + ( llight & 0xFF00 )]; + int alpha = vid.alpha; temp = BLEND_COLOR(temp, vid.color); - int alpha = vid.alpha; if( alpha == 7 ) *lpdest = temp; else if(alpha) @@ -1581,7 +1581,7 @@ void R_PolysetFillSpans8 (spanpackage_t *pspanpackage) // very dirty, maybe need dual colormap? //*lpdest = (vid.colormap[src >> 8 | (llight & 0xFF00)] << 8) | src & 0xff; // 13 bit lighting, 32 light levels - *lpdest = vid.colormap[(src >> 3) | ((llight & 0x1F00) << 5)] | src & 7; + *lpdest = vid.colormap[(src >> 3) | ((llight & 0x1F00) << 5)] | (src & 7); //PGM *lpz = lzi >> 16; diff --git a/r_surf.c b/r_surf.c index a5fb484d..7331205d 100644 --- a/r_surf.c +++ b/r_surf.c @@ -66,7 +66,7 @@ static int rtable[MOD_FRAMES][MOD_FRAMES]; #if 1 -static void R_BuildLightMap( ); +static void R_BuildLightMap( void ); /* =============== R_AddDynamicLights @@ -172,7 +172,7 @@ Combine and scale multiple lightmaps into the floating format in r_blocklights ================= */ -static void R_BuildLightMap( ) +static void R_BuildLightMap( void ) { int smax, tmax; uint *bl, scale; @@ -622,7 +622,7 @@ void R_DrawSurface (void) //============================================================================= #if !id386 -#define BLEND_LM(pix, light) vid.colormap[(pix >> 3) | ((light & 0x1f00) << 5)] | pix & 7; +#define BLEND_LM(pix, light) vid.colormap[(pix >> 3) | ((light & 0x1f00) << 5)] | ( pix & 7 ); /* ================ @@ -1156,7 +1156,7 @@ int D_log2 (int num) //============================================================================= void R_DecalComputeBasis( msurface_t *surf, int flags, vec3_t textureSpaceBasis[3] ); -void R_DrawSurfaceDecals() +void R_DrawSurfaceDecals( void ) { msurface_t *fa = r_drawsurf.surf; decal_t *p; @@ -1266,7 +1266,7 @@ void R_DrawSurfaceDecals() if( transparent ) { - alpha &= src >> 16 - 3; + alpha &= src >> (16 - 3); src = src << 3; } From c8eac04e9b913e8ab14c0fee3e600beb4fafba7d Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Thu, 10 Oct 2019 06:23:57 +0300 Subject: [PATCH 095/115] ref_soft: fix double promotion --- r_aclip.c | 96 ++++++++++++++++++++++++++-------------------------- r_beams.c | 22 ++++++------ r_bsp.c | 10 +++--- r_decals.c | 4 +-- r_edge.c | 30 ++++++++-------- r_local.h | 10 +++--- r_main.c | 8 ++--- r_math.c | 2 +- r_misc.c | 30 ++++++++-------- r_polyse.c | 4 +-- r_rast.c | 8 ++--- r_scan.c | 12 +++---- r_studio.c | 8 ++--- r_surf.c | 2 +- r_trialias.c | 2 +- 15 files changed, 124 insertions(+), 124 deletions(-) diff --git a/r_aclip.c b/r_aclip.c index e807bd61..c1f19611 100644 --- a/r_aclip.c +++ b/r_aclip.c @@ -70,23 +70,23 @@ void R_Alias_clip_left (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) { scale = (float)(RI.aliasvrect.x - pfv0->u) / (pfv1->u - pfv0->u); - out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5; - out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5; - out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5; - out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5; - out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5; - out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5; + out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5f; + out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5f; + out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5f; + out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5f; + out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5f; + out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5f; } else { scale = (float)(RI.aliasvrect.x - pfv1->u) / (pfv0->u - pfv1->u); - out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5; - out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5; - out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5; - out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5; - out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5; - out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5; + out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5f; + out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5f; + out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5f; + out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5f; + out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5f; + out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5f; } } @@ -99,23 +99,23 @@ void R_Alias_clip_right (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) { scale = (float)(RI.aliasvrectright - pfv0->u ) / (pfv1->u - pfv0->u ); - out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5; - out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5; - out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5; - out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5; - out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5; - out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5; + out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5f; + out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5f; + out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5f; + out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5f; + out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5f; + out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5f; } else { scale = (float)(RI.aliasvrectright - pfv1->u ) / (pfv0->u - pfv1->u ); - out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5; - out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5; - out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5; - out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5; - out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5; - out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5; + out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5f; + out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5f; + out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5f; + out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5f; + out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5f; + out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5f; } } @@ -128,23 +128,23 @@ void R_Alias_clip_top (finalvert_t *pfv0, finalvert_t *pfv1, finalvert_t *out) { scale = (float)(RI.aliasvrect.y - pfv0->v) / (pfv1->v - pfv0->v); - out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5; - out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5; - out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5; - out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5; - out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5; - out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5; + out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5f; + out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5f; + out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5f; + out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5f; + out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5f; + out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5f; } else { scale = (float)(RI.aliasvrect.y - pfv1->v) / (pfv0->v - pfv1->v); - out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5; - out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5; - out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5; - out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5; - out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5; - out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5; + out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5f; + out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5f; + out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5f; + out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5f; + out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5f; + out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5f; } } @@ -159,24 +159,24 @@ void R_Alias_clip_bottom (finalvert_t *pfv0, finalvert_t *pfv1, scale = (float)(RI.aliasvrectbottom - pfv0->v) / (pfv1->v - pfv0->v); - out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5; - out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5; - out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5; - out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5; - out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5; - out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5; + out->u = pfv0->u + ( pfv1->u - pfv0->u ) * scale + 0.5f; + out->v = pfv0->v + ( pfv1->v - pfv0->v ) * scale + 0.5f; + out->s = pfv0->s + ( pfv1->s - pfv0->s ) * scale + 0.5f; + out->t = pfv0->t + ( pfv1->t - pfv0->t ) * scale + 0.5f; + out->l = pfv0->l + ( pfv1->l - pfv0->l ) * scale + 0.5f; + out->zi = pfv0->zi + ( pfv1->zi - pfv0->zi) * scale + 0.5f; } else { scale = (float)(RI.aliasvrectbottom - pfv1->v) / (pfv0->v - pfv1->v); - out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5; - out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5; - out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5; - out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5; - out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5; - out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5; + out->u = pfv1->u + ( pfv0->u - pfv1->u ) * scale + 0.5f; + out->v = pfv1->v + ( pfv0->v - pfv1->v ) * scale + 0.5f; + out->s = pfv1->s + ( pfv0->s - pfv1->s ) * scale + 0.5f; + out->t = pfv1->t + ( pfv0->t - pfv1->t ) * scale + 0.5f; + out->l = pfv1->l + ( pfv0->l - pfv1->l ) * scale + 0.5f; + out->zi = pfv1->zi + ( pfv0->zi - pfv1->zi) * scale + 0.5f; } } diff --git a/r_beams.c b/r_beams.c index d6648f40..1f7fa00e 100644 --- a/r_beams.c +++ b/r_beams.c @@ -64,7 +64,7 @@ static void FracNoise( float *noise, int divs ) static void SineNoise( float *noise, int divs ) { float freq = 0; - float step = M_PI / (float)divs; + float step = M_PI_F / (float)divs; int i; for( i = 0; i < divs; i++ ) @@ -236,7 +236,7 @@ static void R_DrawSegs( vec3_t source, vec3_t delta, float width, float scale, f } else { - scale *= length * 2.0; + scale *= length * 2.0f; } // Iterator to resample noise waveform (it needs to be generated in powers of 2) @@ -274,7 +274,7 @@ static void R_DrawSegs( vec3_t source, vec3_t delta, float width, float scale, f { float s, c; - SinCos( fraction * M_PI * length + freq, &s, &c ); + SinCos( fraction * M_PI_F * length + freq, &s, &c ); VectorMA( nextSeg.pos, (factor * s), RI.vup, nextSeg.pos ); // rotate the noise along the perpendicluar axis a bit to keep the bolt from looking diagonal @@ -386,8 +386,8 @@ void R_DrawTorus( vec3_t source, vec3_t delta, float width, float scale, float f if( segments > NOISE_DIVISIONS ) segments = NOISE_DIVISIONS; - length = VectorLength( delta ) * 0.01; - if( length < 0.5 ) length = 0.5; // don't lose all of the noise/texture on short beams + length = VectorLength( delta ) * 0.01f; + if( length < 0.5f ) length = 0.5f; // don't lose all of the noise/texture on short beams div = 1.0f / (segments - 1); @@ -421,7 +421,7 @@ void R_DrawTorus( vec3_t source, vec3_t delta, float width, float scale, float f VectorMA( point, factor, RI.vup, point ); // rotate the noise along the perpendicluar axis a bit to keep the bolt from looking diagonal - factor = rgNoise[noiseIndex>>16] * scale * cos( fraction * M_PI * 3 + freq ); + factor = rgNoise[noiseIndex>>16] * scale * cos( fraction * M_PI_F * 3 + freq ); VectorMA( point, factor, RI.vright, point ); } } @@ -658,11 +658,11 @@ void R_DrawBeamFollow( BEAM *pbeam, float frametime ) VectorMA( delta, pbeam->width, normal, last1 ); VectorMA( delta, -pbeam->width, normal, last2 ); - div = 1.0 / pbeam->amplitude; + div = 1.0f / pbeam->amplitude; fraction = ( pbeam->die - gpGlobals->time ) * div; - vLast = 0.0; - vStep = 1.0; + vLast = 0.0f; + vStep = 1.0f; while( particles ) { @@ -755,7 +755,7 @@ void R_DrawRing( vec3_t source, vec3_t delta, float width, float amplitude, floa if( segments > NOISE_DIVISIONS * 8 ) segments = NOISE_DIVISIONS * 8; - length = VectorLength( delta ) * 0.01f * M_PI; + length = VectorLength( delta ) * 0.01f * M_PI_F; if( length < 0.5f ) length = 0.5f; // Don't lose all of the noise/texture on short beams div = 1.0f / ( segments - 1 ); @@ -811,7 +811,7 @@ void R_DrawRing( vec3_t source, vec3_t delta, float width, float amplitude, floa // Rotate the noise along the perpendicluar axis a bit to keep the bolt from looking diagonal factor = rgNoise[(noiseIndex >> 16) & (NOISE_DIVISIONS - 1)] * scale; - factor *= cos( fraction * M_PI * 24 + freq ); + factor *= cos( fraction * M_PI_F * 24 + freq ); VectorMA( point, factor, RI.vright, point ); // Transform point into screen space diff --git a/r_bsp.c b/r_bsp.c index d78efbcc..a141ba5f 100644 --- a/r_bsp.c +++ b/r_bsp.c @@ -110,7 +110,7 @@ void R_RotateBmodel (void) // yaw angle = RI.currententity->angles[YAW]; - angle = angle * M_PI*2 / 360; + angle = angle * M_PI_F * 2 / 360.0f; s = sin(angle); c = cos(angle); @@ -127,7 +127,7 @@ void R_RotateBmodel (void) // pitch angle = RI.currententity->angles[PITCH]; - angle = angle * M_PI*2 / 360; + angle = angle * M_PI_F * 2 / 360.0f; s = sin(angle); c = cos(angle); @@ -145,7 +145,7 @@ void R_RotateBmodel (void) // roll angle = RI.currententity->angles[ROLL]; - angle = angle * M_PI*2 / 360; + angle = angle * M_PI_F*2 / 360.0f; s = sin(angle); c = cos(angle); @@ -667,7 +667,7 @@ void R_DrawSolidClippedSubmodelPolygons (model_t *pmodel, mnode_t *topnode) { if( psurf->plane->type != PLANE_Z && !FBitSet( RI.currententity->curstate.effects, EF_WATERSIDES )) continue; - if( r_entorigin[2] + pmodel->mins[2] + 1.0 >= psurf->plane->dist ) + if( r_entorigin[2] + pmodel->mins[2] + 1.0f >= psurf->plane->dist ) continue; } // find which side of the node we are on @@ -749,7 +749,7 @@ void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags, mnode_t *topnode) { if( psurf->plane->type != PLANE_Z && !FBitSet( RI.currententity->curstate.effects, EF_WATERSIDES )) continue; - if( r_entorigin[2] + pmodel->mins[2] + 1.0 >= psurf->plane->dist ) + if( r_entorigin[2] + pmodel->mins[2] + 1.0f >= psurf->plane->dist ) continue; } // find which side of the node we are on diff --git a/r_decals.c b/r_decals.c index 4087e2f2..436d9fbb 100644 --- a/r_decals.c +++ b/r_decals.c @@ -410,12 +410,12 @@ static void R_DecalVertsLight( float *v, msurface_t *surf, int vertCount ) // lightmap texture coordinates s = DotProduct( v, info->lmvecs[0] ) + info->lmvecs[0][3] - info->lightmapmins[0]; s += surf->light_s * sample_size; - s += sample_size * 0.5; + s += sample_size * 0.5f; s /= BLOCK_SIZE * sample_size; //fa->texinfo->texture->width; t = DotProduct( v, info->lmvecs[1] ) + info->lmvecs[1][3] - info->lightmapmins[1]; t += surf->light_t * sample_size; - t += sample_size * 0.5; + t += sample_size * 0.5f; t /= BLOCK_SIZE * sample_size; //fa->texinfo->texture->height; v[5] = s; diff --git a/r_edge.c b/r_edge.c index 97cc7985..6a3ac3fe 100644 --- a/r_edge.c +++ b/r_edge.c @@ -474,10 +474,10 @@ void R_LeadingEdge (edge_t *edge) if (surf->insubmodel && (surf->key == surf2->key)) { // must be two bmodels in the same leaf; sort on 1/z - fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000); + fu = (float)(edge->u - 0xFFFFF) * (1.0f / 0x100000); newzi = surf->d_ziorigin + fv*surf->d_zistepv + fu*surf->d_zistepu; - newzibottom = newzi * 0.99; + newzibottom = newzi * 0.99f; testzi = surf2->d_ziorigin + fv*surf2->d_zistepv + fu*surf2->d_zistepu; @@ -487,7 +487,7 @@ void R_LeadingEdge (edge_t *edge) goto newtop; } - newzitop = newzi * 1.01; + newzitop = newzi * 1.01f; if (newzitop >= testzi) { if (surf->d_zistepu >= surf2->d_zistepu) @@ -512,10 +512,10 @@ continue_search: goto continue_search; // must be two bmodels in the same leaf; sort on 1/z - fu = (float)(edge->u - 0xFFFFF) * (1.0 / 0x100000); + fu = (float)(edge->u - 0xFFFFF) * (1.0f / 0x100000); newzi = surf->d_ziorigin + fv*surf->d_zistepv + fu*surf->d_zistepu; - newzibottom = newzi * 0.99; + newzibottom = newzi * 0.99f; testzi = surf2->d_ziorigin + fv*surf2->d_zistepv + fu*surf2->d_zistepu; @@ -525,7 +525,7 @@ continue_search: goto gotposition; } - newzitop = newzi * 1.01; + newzitop = newzi * 1.01f; if (newzitop >= testzi) { if (surf->d_zistepu >= surf2->d_zistepu) @@ -819,7 +819,7 @@ void D_CalcGradients (msurface_t *pface) pplane = pface->plane; - mipscale = 1.0 / (float)(1 << miplevel); + mipscale = 1.0f / (float)(1 << miplevel); if( pface->texinfo->flags & TEX_WORLD_LUXELS ) @@ -829,8 +829,8 @@ void D_CalcGradients (msurface_t *pface) } else { - TransformVector (pface->info->lmvecs[0], p_saxis); - TransformVector (pface->info->lmvecs[1], p_taxis); + TransformVector (pface->info->lmvecs[0], p_saxis); + TransformVector (pface->info->lmvecs[1], p_taxis); } t = xscaleinv * mipscale; @@ -851,19 +851,19 @@ void D_CalcGradients (msurface_t *pface) t = 0x10000*mipscale; if( pface->texinfo->flags & TEX_WORLD_LUXELS ) { - sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) - + sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5f)) - ((pface->texturemins[0] << 16) >> miplevel) + pface->texinfo->vecs[0][3]*t; - tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - + tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5f)) - ((pface->texturemins[1] << 16) >> miplevel) + pface->texinfo->vecs[1][3]*t; } else { - sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) - + sadjust = ((fixed16_t)(DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5f)) - ((pface->info->lightmapmins[0] << 16) >> miplevel) + pface->info->lmvecs[0][3]*t; - tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) - + tadjust = ((fixed16_t)(DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5f)) - ((pface->info->lightmapmins[1] << 16) >> miplevel) + pface->info->lmvecs[1][3]*t; } @@ -872,9 +872,9 @@ void D_CalcGradients (msurface_t *pface) { if(pface->flags & SURF_DRAWTURB) - sadjust += 0x10000 * (-128 * ( (gpGlobals->time * 0.25) - (int)(gpGlobals->time * 0.25) )); + sadjust += 0x10000 * (-128 * ( (gpGlobals->time * 0.25f) - (int)(gpGlobals->time * 0.25f) )); else - sadjust += 0x10000 * (-128 * ( (gpGlobals->time * 0.77) - (int)(gpGlobals->time * 0.77) )); + sadjust += 0x10000 * (-128 * ( (gpGlobals->time * 0.77f) - (int)(gpGlobals->time * 0.77f) )); bbextents = ((pface->extents[0] << 16) >> miplevel) - 1; } else diff --git a/r_local.h b/r_local.h index 6b36d4fa..f8ec142d 100644 --- a/r_local.h +++ b/r_local.h @@ -419,7 +419,7 @@ void R_DrawModelHull( void ); void GL_Bind( int tmu, unsigned int texnum ); // -// gl_draw.c +// gl_draw.cM_PI // void R_Set2DMode( qboolean enable ); void R_DrawTileClear( int texnum, int x, int y, int w, int h ); @@ -821,13 +821,13 @@ extern cvar_t *r_showhull; #define BMODEL_FULLY_CLIPPED 0x10 // value returned by R_BmodelCheckBBox () // if bbox is trivially rejected -#define XCENTERING (1.0 / 2.0) -#define YCENTERING (1.0 / 2.0) +#define XCENTERING (1.0f / 2.0f) +#define YCENTERING (1.0f / 2.0f) -#define CLIP_EPSILON 0.001 +#define CLIP_EPSILON 0.001f // !!! if this is changed, it must be changed in asm_draw.h too !!! -#define NEAR_CLIP 0.01 +#define NEAR_CLIP 0.01f //#define MAXALIASVERTS 2000 // TODO: tune this diff --git a/r_main.c b/r_main.c index 493914c5..c22092a5 100644 --- a/r_main.c +++ b/r_main.c @@ -498,11 +498,11 @@ R_SetupProjectionMatrix static void R_SetupProjectionMatrix( matrix4x4 m ) { #if 1 - double xMin, xMax, yMin, yMax, zNear, zFar; + float xMin, xMax, yMin, yMax, zNear, zFar; if( RI.drawOrtho ) { - ref_overview_t *ov = gEngfuncs.GetOverviewParms(); + const ref_overview_t *ov = gEngfuncs.GetOverviewParms(); Matrix4x4_CreateOrtho( m, ov->xLeft, ov->xRight, ov->yTop, ov->yBottom, ov->zNear, ov->zFar ); return; } @@ -512,10 +512,10 @@ static void R_SetupProjectionMatrix( matrix4x4 m ) zNear = 4.0f; zFar = max( 256.0f, RI.farClip ); - yMax = zNear * tan( RI.fov_y * M_PI / 360.0 ); + yMax = zNear * tan( RI.fov_y * M_PI_F / 360.0f ); yMin = -yMax; - xMax = zNear * tan( RI.fov_x * M_PI / 360.0 ); + xMax = zNear * tan( RI.fov_x * M_PI_F / 360.0f ); xMin = -xMax; Matrix4x4_CreateProjection( m, xMax, xMin, yMax, yMin, zNear, zFar ); diff --git a/r_math.c b/r_math.c index c60e09fa..f8a43d7f 100644 --- a/r_math.c +++ b/r_math.c @@ -169,7 +169,7 @@ void Matrix4x4_CreateRotate( matrix4x4 out, float angle, float x, float y, float y *= len; z *= len; - angle *= (-M_PI / 180.0f); + angle *= (-M_PI_F / 180.0f); SinCos( angle, &s, &c ); out[0][0]=x * x + c * (1 - x * x); diff --git a/r_misc.c b/r_misc.c index e3c00f72..cd2c5653 100644 --- a/r_misc.c +++ b/r_misc.c @@ -221,22 +221,22 @@ void R_ViewChanged (vrect_t *vr) RI.vrect = *vr; - horizontalFieldOfView = 2*tan((float)RI.fov_x/360*M_PI); - verticalFieldOfView = 2*tan((float)RI.fov_y/360*M_PI); + horizontalFieldOfView = 2*tan((float)RI.fov_x/360.0f * M_PI_F); + verticalFieldOfView = 2*tan((float)RI.fov_y/360.0f * M_PI_F); RI.fvrectx = (float)RI.vrect.x; - RI.fvrectx_adj = (float)RI.vrect.x - 0.5; + RI.fvrectx_adj = (float)RI.vrect.x - 0.5f; RI.vrect_x_adj_shift20 = (RI.vrect.x<<20) + (1<<19) - 1; RI.fvrecty = (float)RI.vrect.y; - RI.fvrecty_adj = (float)RI.vrect.y - 0.5; + RI.fvrecty_adj = (float)RI.vrect.y - 0.5f; RI.vrectright = RI.vrect.x + RI.vrect.width; RI.vrectright_adj_shift20 = (RI.vrectright<<20) + (1<<19) - 1; RI.fvrectright = (float)RI.vrectright; - RI.fvrectright_adj = (float)RI.vrectright - 0.5; - RI.vrectrightedge = (float)RI.vrectright - 0.99; + RI.fvrectright_adj = (float)RI.vrectright - 0.5f; + RI.vrectrightedge = (float)RI.vrectright - 0.99f; RI.vrectbottom = RI.vrect.y + RI.vrect.height; RI.fvrectbottom = (float)RI.vrectbottom; - RI.fvrectbottom_adj = (float)RI.vrectbottom - 0.5; + RI.fvrectbottom_adj = (float)RI.vrectbottom - 0.5f; RI.aliasvrect.x = (int)(RI.vrect.x * r_aliasuvscale); RI.aliasvrect.y = (int)(RI.vrect.y * r_aliasuvscale); @@ -257,44 +257,44 @@ void R_ViewChanged (vrect_t *vr) // but will definately render in the [range] row and column, so adjust the // buffer origin to get an exact edge to edge fill xcenter = ((float)RI.vrect.width * XCENTERING) + - RI.vrect.x - 0.5; + RI.vrect.x - 0.5f; aliasxcenter = xcenter * r_aliasuvscale; ycenter = ((float)RI.vrect.height * YCENTERING) + - RI.vrect.y - 0.5; + RI.vrect.y - 0.5f; aliasycenter = ycenter * r_aliasuvscale; xscale = RI.vrect.width / horizontalFieldOfView; aliasxscale = xscale * r_aliasuvscale; - xscaleinv = 1.0 / xscale; + xscaleinv = 1.0f / xscale; yscale = xscale; aliasyscale = yscale * r_aliasuvscale; - yscaleinv = 1.0 / yscale; + yscaleinv = 1.0f / yscale; //xscaleshrink = (RI.vrect.width-6)/RI.horizontalFieldOfView; //yscaleshrink = xscaleshrink; // left side clip - qfrustum.screenedge[0].normal[0] = -1.0 / (xOrigin*horizontalFieldOfView); + qfrustum.screenedge[0].normal[0] = -1.0f / (xOrigin*horizontalFieldOfView); qfrustum.screenedge[0].normal[1] = 0; qfrustum.screenedge[0].normal[2] = 1; qfrustum.screenedge[0].type = PLANE_ANYZ; // right side clip qfrustum.screenedge[1].normal[0] = - 1.0 / ((1.0-xOrigin)*horizontalFieldOfView); + 1.0f / ((1.0f-xOrigin)*horizontalFieldOfView); qfrustum.screenedge[1].normal[1] = 0; qfrustum.screenedge[1].normal[2] = 1; qfrustum.screenedge[1].type = PLANE_ANYZ; // top side clip qfrustum.screenedge[2].normal[0] = 0; - qfrustum.screenedge[2].normal[1] = -1.0 / (yOrigin*verticalFieldOfView); + qfrustum.screenedge[2].normal[1] = -1.0f / (yOrigin*verticalFieldOfView); qfrustum.screenedge[2].normal[2] = 1; qfrustum.screenedge[2].type = PLANE_ANYZ; // bottom side clip qfrustum.screenedge[3].normal[0] = 0; - qfrustum.screenedge[3].normal[1] = 1.0 / ((1.0-yOrigin)*verticalFieldOfView); + qfrustum.screenedge[3].normal[1] = 1.0f / ((1.0f-yOrigin)*verticalFieldOfView); qfrustum.screenedge[3].normal[2] = 1; qfrustum.screenedge[3].type = PLANE_ANYZ; diff --git a/r_polyse.c b/r_polyse.c index 11a48933..e987f33d 100644 --- a/r_polyse.c +++ b/r_polyse.c @@ -369,7 +369,7 @@ void FloorDivMod (float numer, float denom, int *quotient, int q, r; float x; - if (numer >= 0.0) + if (numer >= 0.0f) { x = floor(numer / denom); @@ -730,7 +730,7 @@ qboolean R_PolysetCalcGradients (int skinwidth) printf("%d %d %d %d %d %d\n" , r_p1[0], r_p1[1], r_p1[2] >> 16, r_p1[3] >> 16, r_p1[4], r_p1[5]); printf("%d %d %d %d %d %d\n\n", r_p2[0], r_p2[1], r_p2[2] >> 16, r_p2[3] >> 16, r_p2[4], r_p2[5]); */ - xstepdenominv = 1.0 / (float)d_xdenom; + xstepdenominv = 1.0f / (float)d_xdenom; ystepdenominv = -xstepdenominv; diff --git a/r_rast.c b/r_rast.c index ba6aed4b..5e6590a4 100644 --- a/r_rast.c +++ b/r_rast.c @@ -244,7 +244,7 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) if (transformed[2] < NEAR_CLIP) transformed[2] = NEAR_CLIP; - lzi0 = 1.0 / transformed[2]; + lzi0 = 1.0f / transformed[2]; // FIXME: build x/yscale into transform? scale = xscale * lzi0; @@ -273,7 +273,7 @@ void R_EmitEdge (mvertex_t *pv0, mvertex_t *pv1) if (transformed[2] < NEAR_CLIP) transformed[2] = NEAR_CLIP; - r_lzi1 = 1.0 / transformed[2]; + r_lzi1 = 1.0f / transformed[2]; scale = xscale * r_lzi1; r_u1 = (xcenter + scale*transformed[0]); @@ -736,7 +736,7 @@ void R_RenderFace (msurface_t *fa, int clipflags) // FIXME: cache this? TransformVector (pplane->normal, p_normal); // FIXME: cache this? - distinv = 1.0 / (pplane->dist - DotProduct (tr.modelorg, pplane->normal)); + distinv = 1.0f / (pplane->dist - DotProduct (tr.modelorg, pplane->normal)); surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; @@ -857,7 +857,7 @@ void R_RenderBmodelFace (bedge_t *pedges, msurface_t *psurf) // FIXME: cache this? TransformVector (pplane->normal, p_normal); // FIXME: cache this? - distinv = 1.0 / (pplane->dist - DotProduct (tr.modelorg, pplane->normal)); + distinv = 1.0f / (pplane->dist - DotProduct (tr.modelorg, pplane->normal)); surface_p->d_zistepu = p_normal[0] * xscaleinv * distinv; surface_p->d_zistepv = -p_normal[1] * yscaleinv * distinv; diff --git a/r_scan.c b/r_scan.c index c0e7838b..d096e4b7 100644 --- a/r_scan.c +++ b/r_scan.c @@ -168,7 +168,7 @@ void Turbulent8 (espan_t *pspan) r_turb_sstep = 0; // keep compiler happy r_turb_tstep = 0; // ditto - r_turb_pbase = (unsigned char *)cacheblock; + r_turb_pbase = cacheblock; sdivz16stepu = d_sdivzstepu * 16; tdivz16stepu = d_tdivzstepu * 16; @@ -307,7 +307,7 @@ void TurbulentZ8 (espan_t *pspan, int alpha1) r_turb_sstep = 0; // keep compiler happy r_turb_tstep = 0; // ditto - r_turb_pbase = (unsigned char *)cacheblock; + r_turb_pbase = cacheblock; sdivz16stepu = d_sdivzstepu * 16; tdivz16stepu = d_tdivzstepu * 16; @@ -604,7 +604,7 @@ void D_DrawSpans16 (espan_t *pspan) sstep = 0; // keep compiler happy tstep = 0; // ditto - pbase = (unsigned char *)cacheblock; + pbase = cacheblock; sdivz8stepu = d_sdivzstepu * 8; tdivz8stepu = d_tdivzstepu * 8; @@ -772,7 +772,7 @@ void D_AlphaSpans16 (espan_t *pspan) sstep = 0; // keep compiler happy tstep = 0; // ditto - pbase = (unsigned char *)cacheblock; + pbase = cacheblock; sdivz8stepu = d_sdivzstepu * 8; tdivz8stepu = d_tdivzstepu * 8; @@ -973,7 +973,7 @@ void D_BlendSpans16 (espan_t *pspan, int alpha) sstep = 0; // keep compiler happy tstep = 0; // ditto - pbase = (unsigned char *)cacheblock; + pbase = cacheblock; sdivz8stepu = d_sdivzstepu * 8; tdivz8stepu = d_tdivzstepu * 8; @@ -1175,7 +1175,7 @@ void D_AddSpans16 (espan_t *pspan) sstep = 0; // keep compiler happy tstep = 0; // ditto - pbase = (unsigned char *)cacheblock; + pbase = cacheblock; sdivz8stepu = d_sdivzstepu * 8; tdivz8stepu = d_tdivzstepu * 8; diff --git a/r_studio.c b/r_studio.c index d51e6947..227bde87 100644 --- a/r_studio.c +++ b/r_studio.c @@ -871,7 +871,7 @@ void R_StudioMergeBones( cl_entity_t *e, model_t *m_pSubModel ) matrix3x4 bonematrix; static vec4_t q[MAXSTUDIOBONES]; static float pos[MAXSTUDIOBONES][3]; - double f; + float f; if( e->curstate.sequence >= m_pStudioHeader->numseq ) e->curstate.sequence = 0; @@ -924,7 +924,7 @@ StudioSetupBones */ void R_StudioSetupBones( cl_entity_t *e ) { - double f; + float f; mstudiobone_t *pbones; mstudioseqdesc_t *pseqdesc; mstudioanim_t *panim; @@ -3015,7 +3015,7 @@ void R_StudioEstimateGait( entity_state_t *pplayer ) } else { - m_pPlayerInfo->gaityaw = ( atan2( est_velocity[1], est_velocity[0] ) * 180 / M_PI ); + m_pPlayerInfo->gaityaw = ( atan2( est_velocity[1], est_velocity[0] ) * 180 / M_PI_F ); if( m_pPlayerInfo->gaityaw > 180.0f ) m_pPlayerInfo->gaityaw = 180.0f; if( m_pPlayerInfo->gaityaw < -180.0f ) m_pPlayerInfo->gaityaw = -180.0f; } @@ -3477,7 +3477,7 @@ void R_DrawViewModel( void ) // adjust the depth range to prevent view model from poking into walls //pglDepthRange( gldepthmin, gldepthmin + 0.3f * ( gldepthmax - gldepthmin )); - s_ziscale = (float)0x8000 * (float)0x10000 * 3.0; + s_ziscale = (float)0x8000 * (float)0x10000 * 3.0f; RI.currentmodel = RI.currententity->model; // backface culling for left-handed weapons diff --git a/r_surf.c b/r_surf.c index 7331205d..2257bd2a 100644 --- a/r_surf.c +++ b/r_surf.c @@ -571,7 +571,7 @@ void R_DrawSurface (void) for (u=0 ; uxyz[0]; y = fv->xyz[1]; z = fv->xyz[2]; - zi = 1.0 / z; + zi = 1.0f / z; fv->zi = zi * s_ziscale; From 86867dcbe34049d2b5fd3696e1c0032c0653a650 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 12 Oct 2019 04:05:23 +0700 Subject: [PATCH 096/115] ref_soft: restore fallback gl1 blitter (force enable with -glblit) --- r_context.c | 23 ------ r_glblit.c | 201 ++++++++++++++++++++++++++++++++++------------------ r_local.h | 2 +- r_main.c | 21 ++++-- 4 files changed, 148 insertions(+), 99 deletions(-) diff --git a/r_context.c b/r_context.c index 38aff2bc..b7ab31e7 100644 --- a/r_context.c +++ b/r_context.c @@ -314,15 +314,6 @@ void GAME_EXPORT GL_SetTexCoordArrayMode( void ) } -void GAME_EXPORT GL_InitExtensions( void ) -{ - -} -void GAME_EXPORT GL_ClearExtensions( void ) -{ - -} - void GAME_EXPORT GL_BackendStartFrame( void ) { @@ -432,20 +423,6 @@ byte *GAME_EXPORT Mod_GetCurrentVis( void ) return NULL; } -void GAME_EXPORT GL_SetupAttributes( int safegl ) -{ - gEngfuncs.Con_Reportf( "Creating an extended GL context for debug...\n" ); - gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_FLAGS, REF_GL_CONTEXT_DEBUG_FLAG ); - - // untill we have any blitter in ref api, setup GL - gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_PROFILE_MASK, REF_GL_CONTEXT_PROFILE_COMPATIBILITY ); - gEngfuncs.GL_SetAttribute( REF_GL_DOUBLEBUFFER, 1 ); - - gEngfuncs.GL_SetAttribute( REF_GL_RED_SIZE, 5 ); - gEngfuncs.GL_SetAttribute( REF_GL_GREEN_SIZE, 6 ); - gEngfuncs.GL_SetAttribute( REF_GL_BLUE_SIZE, 5 ); -} - const char *R_GetConfigName( void ) { return "ref_soft"; // software specific cvars will go to ref_soft.cfg diff --git a/r_glblit.c b/r_glblit.c index 1f0ccc59..4fe17424 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -6,6 +6,10 @@ struct swblit_s uint stride; uint bpp; uint rmask, gmask, bmask; + void *(*pLockBuffer)( void ); + void (*pUnlockBuffer)( void ); + void *(*pCreateBuffer)( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b ); + } swblit; @@ -41,10 +45,122 @@ static void APIENTRY GL_DebugOutput( GLuint source, GLuint type, GLuint id, GLui break; } } -unsigned short *buffer; + + +static unsigned short *glbuf; +static int tex; #define LOAD(x) p##x = gEngfuncs.GL_GetProcAddress(#x) + +void GAME_EXPORT GL_SetupAttributes( int safegl ) +{ + gEngfuncs.Con_Reportf( "Creating an extended GL context for debug...\n" ); + gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_FLAGS, REF_GL_CONTEXT_DEBUG_FLAG ); + + // untill we have any blitter in ref api, setup GL + gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_PROFILE_MASK, REF_GL_CONTEXT_PROFILE_COMPATIBILITY ); + gEngfuncs.GL_SetAttribute( REF_GL_DOUBLEBUFFER, 1 ); + + gEngfuncs.GL_SetAttribute( REF_GL_RED_SIZE, 5 ); + gEngfuncs.GL_SetAttribute( REF_GL_GREEN_SIZE, 6 ); + gEngfuncs.GL_SetAttribute( REF_GL_BLUE_SIZE, 5 ); +} + + +void GAME_EXPORT GL_InitExtensions( void ) +{ + +} +void GAME_EXPORT GL_ClearExtensions( void ) +{ + +} + +static void *R_Lock_GL1( void ) +{ + return glbuf; +} + +static void R_Unlock_GL1( void ) +{ + pglViewport( 0, 0, gpGlobals->width, gpGlobals->height ); + pglMatrixMode( GL_PROJECTION ); + pglLoadIdentity(); + pglOrtho( 0, gpGlobals->width, gpGlobals->height, 0, -99999, 99999 ); + pglMatrixMode( GL_MODELVIEW ); + pglLoadIdentity(); + + pglEnable( GL_TEXTURE_2D ); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vid.width, vid.height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, glbuf ); + //gEngfuncs.Con_Printf("%d\n",pglGetError()); + pglBegin( GL_QUADS ); + pglTexCoord2f( 0, 0 ); + pglVertex2f( 0, 0 ); + + pglTexCoord2f( 1, 0 ); + pglVertex2f( vid.width, 0 ); + + pglTexCoord2f( 1, 1 ); + pglVertex2f( vid.width, vid.height ); + + pglTexCoord2f( 0, 1 ); + pglVertex2f( 0, vid.height ); + pglEnd(); + pglDisable( GL_TEXTURE_2D ); + gEngfuncs.GL_SwapBuffers(); +} + +static void *R_CreateBuffer_GL1( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b ) +{ + + LOAD(glBegin); + LOAD(glEnd); + LOAD(glTexCoord2f); + LOAD(glVertex2f); + LOAD(glEnable); + LOAD(glDisable); + LOAD(glTexImage2D); + LOAD(glOrtho); + LOAD(glMatrixMode); + LOAD(glLoadIdentity); + LOAD(glViewport); + LOAD(glBindTexture); + LOAD(glDebugMessageCallbackARB); + LOAD(glDebugMessageControlARB); + LOAD(glGetError); + LOAD(glGenTextures); + LOAD(glTexParameteri); +#ifdef GLDEBUG + if( gpGlobals->developer ) + { + gEngfuncs.Con_Reportf( "Installing GL_DebugOutput...\n"); + pglDebugMessageCallbackARB( GL_DebugOutput, NULL ); + + // force everything to happen in the main thread instead of in a separate driver thread + pglEnable( GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB ); + } + + // enable all the low priority messages + pglDebugMessageControlARB( GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, true ); +#endif + + if( glbuf ) + Mem_Free(glbuf); + glbuf = Mem_Malloc( r_temppool, width*height*2 ); + *stride = width; + *bpp = 2; + *r = MASK(5) << 6 + 5; + *g = MASK(6) << 5; + *b = MASK(5); + return glbuf; +} + + + static int FIRST_BIT( uint mask ) { uint i; @@ -256,43 +372,22 @@ void R_BuildBlendMaps( void ) void R_AllocScreen( void ); -void R_InitBlit(void) +void R_InitBlit( qboolean glblit ) { + R_BuildBlendMaps(); - /*LOAD(glBegin); - LOAD(glEnd); - LOAD(glTexCoord2f); - LOAD(glVertex2f); - LOAD(glEnable); - LOAD(glDisable); - LOAD(glTexImage2D); - LOAD(glOrtho); - LOAD(glMatrixMode); - LOAD(glLoadIdentity); - LOAD(glViewport); - LOAD(glBindTexture); - LOAD(glDebugMessageCallbackARB); - LOAD(glDebugMessageControlARB); - LOAD(glGetError); - LOAD(glGenTextures); - LOAD(glTexParameteri);*/ -#ifdef GLDEBUG - if( gpGlobals->developer ) + if( glblit ) { - gEngfuncs.Con_Reportf( "Installing GL_DebugOutput...\n"); - pglDebugMessageCallbackARB( GL_DebugOutput, NULL ); - - // force everything to happen in the main thread instead of in a separate driver thread - pglEnable( GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB ); + swblit.pLockBuffer = R_Lock_GL1; + swblit.pUnlockBuffer = R_Unlock_GL1; + swblit.pCreateBuffer = R_CreateBuffer_GL1; + } + else + { + swblit.pLockBuffer = gEngfuncs.SW_LockBuffer; + swblit.pUnlockBuffer = gEngfuncs.SW_UnlockBuffer; + swblit.pCreateBuffer = gEngfuncs.SW_CreateBuffer; } - - // enable all the low priority messages - pglDebugMessageControlARB( GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, true ); -#endif - - //buffer = Mem_Malloc( r_temppool, 1920*1080*2 ); - - R_BuildBlendMaps(); R_AllocScreen(); } @@ -304,7 +399,7 @@ void R_AllocScreen( void ) gpGlobals->height = 200; R_InitCaches(); - gEngfuncs.SW_CreateBuffer( gpGlobals->width, gpGlobals->height, &swblit.stride, &swblit.bpp, + swblit.pCreateBuffer( gpGlobals->width, gpGlobals->height, &swblit.stride, &swblit.bpp, &swblit.rmask, &swblit.gmask, &swblit.bmask); R_BuildScreenMap(); vid.width = gpGlobals->width; @@ -323,7 +418,7 @@ void R_BlitScreen( void ) { //memset( vid.buffer, 10, vid.width * vid.height ); int u, v; - void *buffer = gEngfuncs.SW_LockBuffer(); + void *buffer = swblit.pLockBuffer(); if( !buffer || gpGlobals->width != vid.width || gpGlobals->height != vid.height ) { R_AllocScreen(); @@ -383,37 +478,5 @@ void R_BlitScreen( void ) } } -#if 0 - pglViewport( 0, 0, gpGlobals->width, gpGlobals->height ); - pglMatrixMode( GL_PROJECTION ); - pglLoadIdentity(); - pglOrtho( 0, gpGlobals->width, gpGlobals->height, 0, -99999, 99999 ); - pglMatrixMode( GL_MODELVIEW ); - pglLoadIdentity(); - - pglEnable( GL_TEXTURE_2D ); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vid.width, vid.height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, buffer ); - //gEngfuncs.Con_Printf("%d\n",pglGetError()); - pglBegin( GL_QUADS ); - pglTexCoord2f( 0, 0 ); - pglVertex2f( 0, 0 ); - - pglTexCoord2f( 1, 0 ); - pglVertex2f( vid.width, 0 ); - - pglTexCoord2f( 1, 1 ); - pglVertex2f( vid.width, vid.height ); - - pglTexCoord2f( 0, 1 ); - pglVertex2f( 0, vid.height ); - pglEnd(); - pglDisable( GL_TEXTURE_2D ); - gEngfuncs.GL_SwapBuffers(); -// memset( vid.buffer, 0, vid.width * vid.height * 2 ); -#else - gEngfuncs.SW_UnlockBuffer(); -#endif + swblit.pUnlockBuffer(); } diff --git a/r_local.h b/r_local.h index f8ec142d..1fccb3a8 100644 --- a/r_local.h +++ b/r_local.h @@ -1235,7 +1235,7 @@ void R_DrawBrushModel(cl_entity_t *pent); // void R_InitCaches (void); void R_BlitScreen( void ); -void R_InitBlit( void ); +void R_InitBlit( qboolean gl ); // // r_edge.c diff --git a/r_main.c b/r_main.c index c22092a5..ae11f3b4 100644 --- a/r_main.c +++ b/r_main.c @@ -1788,7 +1788,7 @@ void GAME_EXPORT R_EndFrame( void ) // flush any remaining 2D bits R_Set2DMode( false ); - // blit pixels with GL until engine supports REF_SOFT context + // blit pixels R_BlitScreen(); } @@ -1925,6 +1925,8 @@ void R_InitTurb (void) qboolean GAME_EXPORT R_Init( void ) { + qboolean glblit = false; + gl_emboss_scale = gEngfuncs.Cvar_Get( "gl_emboss_scale", "0", FCVAR_ARCHIVE|FCVAR_LATCH, "fake bumpmapping scale" ); vid_gamma = gEngfuncs.pfnGetCvarPointer( "gamma", 0 ); r_norefresh = gEngfuncs.Cvar_Get( "r_norefresh", "0", 0, "disable 3D rendering (use with caution)" ); @@ -1969,18 +1971,25 @@ qboolean GAME_EXPORT R_Init( void ) tracerblue = gEngfuncs.Cvar_Get( "tracerblue", "0.4", 0, "tracer blue component weight ( 0 - 1.0 )" ); traceralpha = gEngfuncs.Cvar_Get( "traceralpha", "0.5", 0, "tracer alpha amount ( 0 - 1.0 )" ); - // create the window and set up the context - r_temppool = Mem_AllocPool( "ref_sw zone" ); + r_temppool = Mem_AllocPool( "ref_soft zone" ); - if( !gEngfuncs.R_Init_Video( REF_SOFTWARE )) // request GL context + glblit = !!gEngfuncs.Sys_CheckParm( "-glblit" ); + + // create the window and set up the context + if( !glblit && !gEngfuncs.R_Init_Video( REF_SOFTWARE )) // request software blitter { gEngfuncs.R_Free_Video(); + gEngfuncs.Con_Printf("failed to initialize software blitter, fallback to glblit\n"); + glblit = true; + } - gEngfuncs.Host_Error( "Can't initialize video subsystem\nProbably driver was not installed" ); + if( glblit && !gEngfuncs.R_Init_Video( REF_GL )) // request GL context + { + gEngfuncs.R_Free_Video(); return false; } - R_InitBlit(); + R_InitBlit( glblit ); R_InitImages(); // init draw stack From 05d793c34beb21695686df9ad994bea36547a429 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 12 Oct 2019 04:18:05 +0700 Subject: [PATCH 097/115] ref_soft: glblit: refactor --- r_glblit.c | 79 +++++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 40 deletions(-) diff --git a/r_glblit.c b/r_glblit.c index 4fe17424..e43f0363 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -70,6 +70,36 @@ void GAME_EXPORT GL_SetupAttributes( int safegl ) void GAME_EXPORT GL_InitExtensions( void ) { + LOAD(glBegin); + LOAD(glEnd); + LOAD(glTexCoord2f); + LOAD(glVertex2f); + LOAD(glEnable); + LOAD(glDisable); + LOAD(glTexImage2D); + LOAD(glOrtho); + LOAD(glMatrixMode); + LOAD(glLoadIdentity); + LOAD(glViewport); + LOAD(glBindTexture); + LOAD(glDebugMessageCallbackARB); + LOAD(glDebugMessageControlARB); + LOAD(glGetError); + LOAD(glGenTextures); + LOAD(glTexParameteri); +#ifdef GLDEBUG + if( gpGlobals->developer ) + { + gEngfuncs.Con_Reportf( "Installing GL_DebugOutput...\n"); + pglDebugMessageCallbackARB( GL_DebugOutput, NULL ); + + // force everything to happen in the main thread instead of in a separate driver thread + pglEnable( GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB ); + } + + // enable all the low priority messages + pglDebugMessageControlARB( GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, true ); +#endif } void GAME_EXPORT GL_ClearExtensions( void ) @@ -84,16 +114,6 @@ static void *R_Lock_GL1( void ) static void R_Unlock_GL1( void ) { - pglViewport( 0, 0, gpGlobals->width, gpGlobals->height ); - pglMatrixMode( GL_PROJECTION ); - pglLoadIdentity(); - pglOrtho( 0, gpGlobals->width, gpGlobals->height, 0, -99999, 99999 ); - pglMatrixMode( GL_MODELVIEW ); - pglLoadIdentity(); - - pglEnable( GL_TEXTURE_2D ); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vid.width, vid.height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, glbuf ); //gEngfuncs.Con_Printf("%d\n",pglGetError()); @@ -110,43 +130,22 @@ static void R_Unlock_GL1( void ) pglTexCoord2f( 0, 1 ); pglVertex2f( 0, vid.height ); pglEnd(); - pglDisable( GL_TEXTURE_2D ); gEngfuncs.GL_SwapBuffers(); } static void *R_CreateBuffer_GL1( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b ) { + pglViewport( 0, 0, gpGlobals->width, gpGlobals->height ); + pglMatrixMode( GL_PROJECTION ); + pglLoadIdentity(); + pglOrtho( 0, gpGlobals->width, gpGlobals->height, 0, -99999, 99999 ); + pglMatrixMode( GL_MODELVIEW ); + pglLoadIdentity(); - LOAD(glBegin); - LOAD(glEnd); - LOAD(glTexCoord2f); - LOAD(glVertex2f); - LOAD(glEnable); - LOAD(glDisable); - LOAD(glTexImage2D); - LOAD(glOrtho); - LOAD(glMatrixMode); - LOAD(glLoadIdentity); - LOAD(glViewport); - LOAD(glBindTexture); - LOAD(glDebugMessageCallbackARB); - LOAD(glDebugMessageControlARB); - LOAD(glGetError); - LOAD(glGenTextures); - LOAD(glTexParameteri); -#ifdef GLDEBUG - if( gpGlobals->developer ) - { - gEngfuncs.Con_Reportf( "Installing GL_DebugOutput...\n"); - pglDebugMessageCallbackARB( GL_DebugOutput, NULL ); - - // force everything to happen in the main thread instead of in a separate driver thread - pglEnable( GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB ); - } + pglEnable( GL_TEXTURE_2D ); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - // enable all the low priority messages - pglDebugMessageControlARB( GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, true ); -#endif if( glbuf ) Mem_Free(glbuf); From e1efacb3995c8f8fc965d0c366c979d0730eba99 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 12 Oct 2019 14:11:55 +0700 Subject: [PATCH 098/115] ref_soft: glblit: GLES1 blitter --- r_glblit.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 97 insertions(+), 8 deletions(-) diff --git a/r_glblit.c b/r_glblit.c index e43f0363..17947735 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -8,7 +8,7 @@ struct swblit_s uint rmask, gmask, bmask; void *(*pLockBuffer)( void ); void (*pUnlockBuffer)( void ); - void *(*pCreateBuffer)( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b ); + qboolean(*pCreateBuffer)( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b ); } swblit; @@ -50,16 +50,21 @@ static void APIENTRY GL_DebugOutput( GLuint source, GLuint type, GLuint id, GLui static unsigned short *glbuf; static int tex; -#define LOAD(x) p##x = gEngfuncs.GL_GetProcAddress(#x) +#define LOAD(x) p##x = gEngfuncs.GL_GetProcAddress(#x); \ + gEngfuncs.Con_Printf(#x " : %p\n",p##x) void GAME_EXPORT GL_SetupAttributes( int safegl ) { +#if GLDEBUG gEngfuncs.Con_Reportf( "Creating an extended GL context for debug...\n" ); gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_FLAGS, REF_GL_CONTEXT_DEBUG_FLAG ); - +#endif // untill we have any blitter in ref api, setup GL - gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_PROFILE_MASK, REF_GL_CONTEXT_PROFILE_COMPATIBILITY ); + gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_PROFILE_MASK, REF_GL_CONTEXT_PROFILE_ES); + gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_EGL, 1 ); + gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_MAJOR_VERSION, 1 ); + gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_MINOR_VERSION, 1 ); gEngfuncs.GL_SetAttribute( REF_GL_DOUBLEBUFFER, 1 ); gEngfuncs.GL_SetAttribute( REF_GL_RED_SIZE, 5 ); @@ -67,7 +72,12 @@ void GAME_EXPORT GL_SetupAttributes( int safegl ) gEngfuncs.GL_SetAttribute( REF_GL_BLUE_SIZE, 5 ); } +void (*pglOrthof)(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat zNear, GLfloat zFar); +void GL_FUNCTION( glBindBuffer)(GLenum target, GLuint buffer); +void GL_FUNCTION( glBufferData )(GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage); +void GL_FUNCTION( glGenBuffers )(GLsizei n, GLuint *buffers); +void GL_FUNCTION( glDeleteBuffers )(GLsizei n, const GLuint *buffers); void GAME_EXPORT GL_InitExtensions( void ) { LOAD(glBegin); @@ -78,6 +88,7 @@ void GAME_EXPORT GL_InitExtensions( void ) LOAD(glDisable); LOAD(glTexImage2D); LOAD(glOrtho); + LOAD(glOrthof); LOAD(glMatrixMode); LOAD(glLoadIdentity); LOAD(glViewport); @@ -87,7 +98,22 @@ void GAME_EXPORT GL_InitExtensions( void ) LOAD(glGetError); LOAD(glGenTextures); LOAD(glTexParameteri); -#ifdef GLDEBUG + LOAD(glEnableClientState); + LOAD(glDisableClientState); + LOAD(glVertexPointer); + LOAD(glTexCoordPointer); + LOAD(glDrawElements); + LOAD(glClear); + LOAD(glClearColor); + LOAD(glGetString); + LOAD(glColor4f); + LOAD(glDrawArrays); + LOAD(glBindBuffer); + LOAD(glBufferData); + LOAD(glGenBuffers); + LOAD(glDeleteBuffers); + gEngfuncs.Con_Printf("version:%s\n",pglGetString(GL_VERSION)); +#if GLDEBUG if( gpGlobals->developer ) { gEngfuncs.Con_Reportf( "Installing GL_DebugOutput...\n"); @@ -133,6 +159,20 @@ static void R_Unlock_GL1( void ) gEngfuncs.GL_SwapBuffers(); } + +static void R_Unlock_GLES1( void ) +{ + + pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vid.width, vid.height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, glbuf ); + + //gEngfuncs.Con_Printf("%d\n",pglGetError()); + + pglColor4f(1,1,1,1); + pglDrawArrays(GL_TRIANGLE_FAN, 0,4); + //gEngfuncs.Con_Printf("%d\n",pglGetError()); + gEngfuncs.GL_SwapBuffers(); +} + static void *R_CreateBuffer_GL1( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b ) { pglViewport( 0, 0, gpGlobals->width, gpGlobals->height ); @@ -146,7 +186,6 @@ static void *R_CreateBuffer_GL1( int width, int height, uint *stride, uint *bpp, pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - if( glbuf ) Mem_Free(glbuf); glbuf = Mem_Malloc( r_temppool, width*height*2 ); @@ -158,6 +197,56 @@ static void *R_CreateBuffer_GL1( int width, int height, uint *stride, uint *bpp, return glbuf; } +static qboolean R_CreateBuffer_GLES1( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b ) +{ + float data[] = { + 0, 0, + width, 0, + width, height, + 0, height, + 0,0, + 1,0, + 1,1, + 0,1 + }; + int vbo; + pglViewport( 0, 0, gpGlobals->width, gpGlobals->height ); + pglMatrixMode( GL_PROJECTION ); + pglLoadIdentity(); + pglOrthof( 0, gpGlobals->width, gpGlobals->height, 0, -99999, 99999 ); + pglMatrixMode( GL_MODELVIEW ); + pglLoadIdentity(); + + pglEnable( GL_TEXTURE_2D ); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + + if( vbo ) + pglDeleteBuffers( 1,&vbo); + pglGenBuffers(1,&vbo); + pglBindBuffer(GL_ARRAY_BUFFER_ARB,vbo); + pglBufferData(GL_ARRAY_BUFFER_ARB,16*4,data, GL_STATIC_DRAW_ARB); + + pglEnableClientState(GL_VERTEX_ARRAY); + pglEnableClientState(GL_TEXTURE_COORD_ARRAY); + + pglVertexPointer(2,GL_FLOAT,8, 0); + pglTexCoordPointer(2,GL_FLOAT,8,(void*)32); + pglBindBuffer(GL_ARRAY_BUFFER_ARB,0); + + + if( glbuf ) + Mem_Free(glbuf); + glbuf = Mem_Malloc( r_temppool, width*height*2 ); + *stride = width; + *bpp = 2; + *r = MASK(5) << 6 + 5; + *g = MASK(6) << 5; + *b = MASK(5); + return true; +} + static int FIRST_BIT( uint mask ) @@ -378,8 +467,8 @@ void R_InitBlit( qboolean glblit ) if( glblit ) { swblit.pLockBuffer = R_Lock_GL1; - swblit.pUnlockBuffer = R_Unlock_GL1; - swblit.pCreateBuffer = R_CreateBuffer_GL1; + swblit.pUnlockBuffer = R_Unlock_GLES1; + swblit.pCreateBuffer = R_CreateBuffer_GLES1; } else { From 2493659b2383b572239b324a8dd5804965adcf63 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 12 Oct 2019 22:36:21 +0700 Subject: [PATCH 099/115] ref_soft: glblit: change projection scale --- r_glblit.c | 73 +++++++++++++++++++++++++++--------------------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/r_glblit.c b/r_glblit.c index 17947735..834ad2a2 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -148,13 +148,13 @@ static void R_Unlock_GL1( void ) pglVertex2f( 0, 0 ); pglTexCoord2f( 1, 0 ); - pglVertex2f( vid.width, 0 ); + pglVertex2f( 1, 0 ); pglTexCoord2f( 1, 1 ); - pglVertex2f( vid.width, vid.height ); + pglVertex2f( 1, 1 ); pglTexCoord2f( 0, 1 ); - pglVertex2f( 0, vid.height ); + pglVertex2f( 0, 1 ); pglEnd(); gEngfuncs.GL_SwapBuffers(); } @@ -162,23 +162,18 @@ static void R_Unlock_GL1( void ) static void R_Unlock_GLES1( void ) { - pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vid.width, vid.height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, glbuf ); + pglDrawArrays( GL_TRIANGLE_FAN, 0,4 ); - //gEngfuncs.Con_Printf("%d\n",pglGetError()); - - pglColor4f(1,1,1,1); - pglDrawArrays(GL_TRIANGLE_FAN, 0,4); - //gEngfuncs.Con_Printf("%d\n",pglGetError()); gEngfuncs.GL_SwapBuffers(); } -static void *R_CreateBuffer_GL1( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b ) +static qboolean R_CreateBuffer_GL1( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b ) { - pglViewport( 0, 0, gpGlobals->width, gpGlobals->height ); + pglViewport( 0, 0, width, height ); pglMatrixMode( GL_PROJECTION ); pglLoadIdentity(); - pglOrtho( 0, gpGlobals->width, gpGlobals->height, 0, -99999, 99999 ); + pglOrtho( 0, 1, 1, 0, -99999, 99999 ); pglMatrixMode( GL_MODELVIEW ); pglLoadIdentity(); @@ -188,62 +183,68 @@ static void *R_CreateBuffer_GL1( int width, int height, uint *stride, uint *bpp, if( glbuf ) Mem_Free(glbuf); + glbuf = Mem_Malloc( r_temppool, width*height*2 ); + *stride = width; *bpp = 2; *r = MASK(5) << 6 + 5; *g = MASK(6) << 5; *b = MASK(5); - return glbuf; + + return true; } static qboolean R_CreateBuffer_GLES1( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b ) { float data[] = { - 0, 0, - width, 0, - width, height, - 0, height, - 0,0, - 1,0, - 1,1, - 0,1 + // quad verts match texcoords + 0, 0, + 1, 0, + 1, 1, + 0, 1, }; int vbo; - pglViewport( 0, 0, gpGlobals->width, gpGlobals->height ); + + pglViewport( 0, 0, width, height ); pglMatrixMode( GL_PROJECTION ); pglLoadIdentity(); - pglOrthof( 0, gpGlobals->width, gpGlobals->height, 0, -99999, 99999 ); + // project 0..1 to screen size + pglOrthof( 0, 1, 1, 0, -99999, 99999 ); pglMatrixMode( GL_MODELVIEW ); pglLoadIdentity(); pglEnable( GL_TEXTURE_2D ); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - + pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); if( vbo ) - pglDeleteBuffers( 1,&vbo); - pglGenBuffers(1,&vbo); - pglBindBuffer(GL_ARRAY_BUFFER_ARB,vbo); - pglBufferData(GL_ARRAY_BUFFER_ARB,16*4,data, GL_STATIC_DRAW_ARB); + pglDeleteBuffers( 1,&vbo ); + + pglGenBuffers( 1,&vbo ); + pglBindBuffer( GL_ARRAY_BUFFER_ARB, vbo ); + pglBufferData( GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW_ARB ); - pglEnableClientState(GL_VERTEX_ARRAY); - pglEnableClientState(GL_TEXTURE_COORD_ARRAY); + pglEnableClientState( GL_VERTEX_ARRAY ); + pglEnableClientState( GL_TEXTURE_COORD_ARRAY ); - pglVertexPointer(2,GL_FLOAT,8, 0); - pglTexCoordPointer(2,GL_FLOAT,8,(void*)32); - pglBindBuffer(GL_ARRAY_BUFFER_ARB,0); + pglVertexPointer( 2, GL_FLOAT, 8, 0 ); + pglTexCoordPointer( 2, GL_FLOAT, 8, 0 ); + pglBindBuffer( GL_ARRAY_BUFFER_ARB, 0 ) ; + pglColor4f( 1, 1, 1, 1 ); if( glbuf ) - Mem_Free(glbuf); + Mem_Free( glbuf ); + glbuf = Mem_Malloc( r_temppool, width*height*2 ); + *stride = width; *bpp = 2; *r = MASK(5) << 6 + 5; *g = MASK(6) << 5; *b = MASK(5); + return true; } From f376d5d59c5479c05cd52f734039b55a46785d27 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sun, 13 Oct 2019 03:52:47 +0700 Subject: [PATCH 100/115] ref_soft: glblit: gles3 pbo+fbo blitter --- r_glblit.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 104 insertions(+), 6 deletions(-) diff --git a/r_glblit.c b/r_glblit.c index 834ad2a2..9309b962 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -61,10 +61,10 @@ void GAME_EXPORT GL_SetupAttributes( int safegl ) gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_FLAGS, REF_GL_CONTEXT_DEBUG_FLAG ); #endif // untill we have any blitter in ref api, setup GL - gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_PROFILE_MASK, REF_GL_CONTEXT_PROFILE_ES); + gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_PROFILE_MASK, REF_GL_CONTEXT_PROFILE_ES ); gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_EGL, 1 ); - gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_MAJOR_VERSION, 1 ); - gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_MINOR_VERSION, 1 ); + gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_MAJOR_VERSION, 3 ); + gEngfuncs.GL_SetAttribute( REF_GL_CONTEXT_MINOR_VERSION, 0 ); gEngfuncs.GL_SetAttribute( REF_GL_DOUBLEBUFFER, 1 ); gEngfuncs.GL_SetAttribute( REF_GL_RED_SIZE, 5 ); @@ -78,6 +78,13 @@ void GL_FUNCTION( glBindBuffer)(GLenum target, GLuint buffer); void GL_FUNCTION( glBufferData )(GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage); void GL_FUNCTION( glGenBuffers )(GLsizei n, GLuint *buffers); void GL_FUNCTION( glDeleteBuffers )(GLsizei n, const GLuint *buffers); +GLvoid* GL_FUNCTION( glMapBuffer )(GLenum target, GLenum access); +GLboolean GL_FUNCTION( glUnmapBuffer )(GLenum target); +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_FRAMEBUFFER 0x8D40 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 void GAME_EXPORT GL_InitExtensions( void ) { LOAD(glBegin); @@ -112,6 +119,13 @@ void GAME_EXPORT GL_InitExtensions( void ) LOAD(glBufferData); LOAD(glGenBuffers); LOAD(glDeleteBuffers); + LOAD(glMapBuffer); + LOAD(glUnmapBuffer); + LOAD(glGenFramebuffers); + LOAD(glBindFramebuffer); + LOAD(glFramebufferTexture2D); + LOAD(glBlitFramebuffer); + LOAD(glGenTextures); gEngfuncs.Con_Printf("version:%s\n",pglGetString(GL_VERSION)); #if GLDEBUG if( gpGlobals->developer ) @@ -248,6 +262,90 @@ static qboolean R_CreateBuffer_GLES1( int width, int height, uint *stride, uint return true; } +static void *R_Lock_GLES3( void ) +{ + pglBufferData( GL_PIXEL_UNPACK_BUFFER, vid.width * vid.height * 2, 0, GL_STREAM_DRAW_ARB ); + return pglMapBuffer( GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY_ARB ); +} + + +static void R_Unlock_GLES3( void ) +{ + gEngfuncs.GL_SwapBuffers(); + pglUnmapBuffer( GL_PIXEL_UNPACK_BUFFER ); + pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, vid.width, vid.height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0 ); + //pglDrawArrays( GL_TRIANGLE_FAN, 0,4 ); + pglBlitFramebuffer( 0, vid.height, vid.width, 0, 0, 0, vid.width, vid.height, GL_COLOR_BUFFER_BIT, GL_NEAREST ); + + +} + +static qboolean R_CreateBuffer_GLES3( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b ) +{ + float data[] = { + // quad verts match texcoords + 0, 0, + 1, 0, + 1, 1, + 0, 1, + }; + int vbo, pbo, fbo, to; + + // shitty fbo does not work without texture objects :( + pglGenTextures( 1, &to ); + pglBindTexture( GL_TEXTURE_2D, to ); + pglViewport( 0, 0, width, height ); + /*pglMatrixMode( GL_PROJECTION ); + pglLoadIdentity(); + // project 0..1 to screen size + pglOrtho( 0, 1, 1, 0, -99999, 99999 ); + pglMatrixMode( GL_MODELVIEW ); + pglLoadIdentity(); + + pglEnable( GL_TEXTURE_2D ); + pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + + if( vbo ) + pglDeleteBuffers( 1,&vbo ); +*/ + + if( pbo ) + pglDeleteBuffers( 1,&pbo ); + + //pglGenBuffers( 1,&vbo ); + pglGenBuffers( 1, &pbo ); + //pglBindBuffer( GL_ARRAY_BUFFER_ARB, vbo ); + //pglBufferData( GL_ARRAY_BUFFER_ARB, sizeof(data), data, GL_STATIC_DRAW_ARB ); + + //pglEnableClientState( GL_VERTEX_ARRAY ); + //pglEnableClientState( GL_TEXTURE_COORD_ARRAY ); + + //pglVertexPointer( 2, GL_FLOAT, 8, 0 ); + //pglTexCoordPointer( 2, GL_FLOAT, 8, 0 ); + //pglBindBuffer( GL_ARRAY_BUFFER_ARB, 0 ); + + pglBindBuffer( GL_PIXEL_UNPACK_BUFFER, pbo ); + pglBufferData( GL_PIXEL_UNPACK_BUFFER, width * height * 2, 0, GL_STREAM_DRAW_ARB ); + pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0 ); + + pglGenFramebuffers(1, &fbo); + pglBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + pglFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, to, 0); + pglBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + + //pglColor4f( 1, 1, 1, 1 ); + + + *stride = width; + *bpp = 2; + *r = MASK(5) << 6 + 5; + *g = MASK(6) << 5; + *b = MASK(5); + + return true; +} + static int FIRST_BIT( uint mask ) @@ -467,9 +565,9 @@ void R_InitBlit( qboolean glblit ) if( glblit ) { - swblit.pLockBuffer = R_Lock_GL1; - swblit.pUnlockBuffer = R_Unlock_GLES1; - swblit.pCreateBuffer = R_CreateBuffer_GLES1; + swblit.pLockBuffer = R_Lock_GLES3; + swblit.pUnlockBuffer = R_Unlock_GLES3; + swblit.pCreateBuffer = R_CreateBuffer_GLES3; } else { From 9c7c279a5bb5d83e7f586bca61744ace23480db2 Mon Sep 17 00:00:00 2001 From: mittorn Date: Tue, 29 Oct 2019 13:16:16 +0700 Subject: [PATCH 101/115] ref_soft: XASH_LOW_MEMORY --- r_local.h | 9 +++++++-- r_studio.c | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/r_local.h b/r_local.h index 1fccb3a8..893157ff 100644 --- a/r_local.h +++ b/r_local.h @@ -35,7 +35,6 @@ typedef struct mip_s mip_t; typedef int fixed8_t; typedef int fixed16_t; - #define offsetof(s,m) (size_t)&(((s *)0)->m) #define ASSERT(x) if(!( x )) gEngfuncs.Host_Error( "assert failed at %s:%i\n", __FILE__, __LINE__ ) @@ -62,10 +61,16 @@ extern byte *r_temppool; #define BLOCK_SIZE_MAX 1024 #define MAX_TEXTURES 4096 +#define MAX_DECAL_SURFS 4096 + +#if XASH_LOW_MEMORY + #define MAX_TEXTURES 1024 + #define MAX_DECAL_SURFS 256 +#endif + #define MAX_DETAIL_TEXTURES 256 #define MAX_LIGHTMAPS 256 #define SUBDIVIDE_SIZE 64 -#define MAX_DECAL_SURFS 4096 #define MAX_DRAW_STACK 2 // normal view and menu view #define SHADEDOT_QUANT 16 // precalculated dot products for quantized angles diff --git a/r_studio.c b/r_studio.c index 227bde87..807bcab3 100644 --- a/r_studio.c +++ b/r_studio.c @@ -56,6 +56,10 @@ typedef struct sortedmesh_s int flags; // face flags } sortedmesh_t; +#if XASH_LOW_MEMORY + #define MAXSTUDIOVERTS 1024 +#endif + typedef struct { double time; From b3ad557dd287891a20fd9a6516e595881a820fa9 Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 31 Oct 2019 01:43:40 +0700 Subject: [PATCH 102/115] ref_soft: update api, display rotation support --- r_context.c | 1 + r_glblit.c | 194 +++++++++++++++++++++++++++++++++++++++------------- r_local.h | 1 + r_main.c | 2 +- 4 files changed, 151 insertions(+), 47 deletions(-) diff --git a/r_context.c b/r_context.c index b7ab31e7..a576492d 100644 --- a/r_context.c +++ b/r_context.c @@ -433,6 +433,7 @@ ref_interface_t gReffuncs = R_Init, R_Shutdown, R_GetConfigName, + R_SetDisplayTransform, GL_SetupAttributes, GL_InitExtensions, diff --git a/r_glblit.c b/r_glblit.c index 9309b962..d9a6c169 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -9,10 +9,38 @@ struct swblit_s void *(*pLockBuffer)( void ); void (*pUnlockBuffer)( void ); qboolean(*pCreateBuffer)( int width, int height, uint *stride, uint *bpp, uint *r, uint *g, uint *b ); - + uint rotate; } swblit; +qboolean R_SetDisplayTransform( uint rotate, int offset_x, int offset_y, float scale_x, float scale_y ) +{ + qboolean ret = true; + if( rotate > 1 ) + { + gEngfuncs.Con_Printf("only 0-1 rotation supported\n"); + ret = false; + } + else + swblit.rotate = rotate; + + if( offset_x || offset_y ) + { + // it is possible implement for offset > 0 + gEngfuncs.Con_Printf("offset transform not supported\n"); + ret = false; + } + + if( scale_x != 1.0f || scale_y != 1.0f ) + { + // maybe implement 2x2? + gEngfuncs.Con_Printf("scale transform not supported\n"); + ret = false; + } + + return ret; +} + /* ======================== DebugCallback @@ -202,7 +230,7 @@ static qboolean R_CreateBuffer_GL1( int width, int height, uint *stride, uint *b *stride = width; *bpp = 2; - *r = MASK(5) << 6 + 5; + *r = MASK(5) << (6 + 5); *g = MASK(6) << 5; *b = MASK(5); @@ -255,7 +283,7 @@ static qboolean R_CreateBuffer_GLES1( int width, int height, uint *stride, uint *stride = width; *bpp = 2; - *r = MASK(5) << 6 + 5; + *r = MASK(5) << (6 + 5); *g = MASK(6) << 5; *b = MASK(5); @@ -339,7 +367,7 @@ static qboolean R_CreateBuffer_GLES3( int width, int height, uint *stride, uint *stride = width; *bpp = 2; - *r = MASK(5) << 6 + 5; + *r = MASK(5) << (6 + 5); *g = MASK(6) << 5; *b = MASK(5); @@ -580,90 +608,164 @@ void R_InitBlit( qboolean glblit ) void R_AllocScreen( void ) { - if( gpGlobals->width < 320 ) - gpGlobals->width = 320; - if( gpGlobals->height < 200 ) - gpGlobals->height = 200; + int w, h; + + if( gpGlobals->width < 128 ) + gpGlobals->width = 128; + if( gpGlobals->height < 128 ) + gpGlobals->height = 128; R_InitCaches(); - swblit.pCreateBuffer( gpGlobals->width, gpGlobals->height, &swblit.stride, &swblit.bpp, + + if( swblit.rotate ) + w = gpGlobals->height, h = gpGlobals->width; + else + h = gpGlobals->height, w = gpGlobals->width; + + swblit.pCreateBuffer( w, h, &swblit.stride, &swblit.bpp, &swblit.rmask, &swblit.gmask, &swblit.bmask); R_BuildScreenMap(); vid.width = gpGlobals->width; vid.height = gpGlobals->height; vid.rowbytes = gpGlobals->width; // rowpixels if( d_pzbuffer ) - Mem_Free( d_pzbuffer ); - d_pzbuffer = Mem_Calloc( r_temppool, vid.width*vid.height*2 + 64 ); + free( d_pzbuffer ); + d_pzbuffer = malloc( vid.width*vid.height*2 + 64 ); if( vid.buffer ) - Mem_Free( vid.buffer ); + free( vid.buffer ); - vid.buffer = Mem_Malloc( r_temppool, vid.width * vid.height*sizeof( pixel_t ) ); + vid.buffer = malloc( vid.width * vid.height*sizeof( pixel_t ) ); } void R_BlitScreen( void ) { - //memset( vid.buffer, 10, vid.width * vid.height ); int u, v; void *buffer = swblit.pLockBuffer(); +// gEngfuncs.Con_Printf("blit begin\n"); + //memset( vid.buffer, 10, vid.width * vid.height ); + if( !buffer || gpGlobals->width != vid.width || gpGlobals->height != vid.height ) { + gEngfuncs.Con_Printf("pre allocscrn\n"); R_AllocScreen(); + gEngfuncs.Con_Printf("post allocscrn\n"); return; } + //return; //byte *buf = vid.buffer; //#pragma omp parallel for schedule(static) - if( swblit.bpp == 2 ) + //gEngfuncs.Con_Printf("swblit %d %d", swblit.bpp, vid.height ); + if( swblit.rotate ) { - unsigned short *pbuf = buffer; - for( v = 0; v < vid.height;v++) + if( swblit.bpp == 2 ) { - uint start = vid.rowbytes * v; - uint dstart = swblit.stride * v; - - for( u = 0; u < vid.width; u++ ) + unsigned short *pbuf = buffer; + for( v = 0; v < 10;v++) { - unsigned int s = vid.screen[vid.buffer[start + u]]; - pbuf[dstart + u] = s; + uint start = vid.rowbytes * v; + uint d = swblit.stride - v - 1; + + for( u = 0; u < vid.width; u++ ) + { + unsigned int s = vid.screen[vid.buffer[start + u]]; + pbuf[d] = s; + d += swblit.stride; + } } } - } - else if( swblit.bpp == 4 ) - { - unsigned int *pbuf = buffer; - - for( v = 0; v < vid.height;v++) + else if( swblit.bpp == 4 ) { - uint start = vid.rowbytes * v; - uint dstart = swblit.stride * v; + unsigned int *pbuf = buffer; - for( u = 0; u < vid.width; u++ ) + for( v = 0; v < vid.height;v++) + { + uint start = vid.rowbytes * v; + uint d = swblit.stride - v - 1; + + for( u = 0; u < vid.width; u++ ) + { + unsigned int s = vid.screen32[vid.buffer[start + u]]; + pbuf[d] = s; + d += swblit.stride; + } + } + } + else if( swblit.bpp == 3 ) + { + byte *pbuf = buffer; + for( v = 0; v < 10;v++) { - unsigned int s = vid.screen32[vid.buffer[start + u]]; - pbuf[dstart + u] = s; + uint start = vid.rowbytes * v; + uint d = swblit.stride - v - 1; + + for( u = 0; u < vid.width; u++ ) + { + unsigned int s = vid.screen32[vid.buffer[start + u]]; + pbuf[(d)*3] = s; + s = s >> 8; + pbuf[(d)*3+1] = s; + s = s >> 8; + pbuf[(d)*3+2] = s; + d += swblit.stride; + } } } } - else if( swblit.bpp == 3 ) + else { - byte *pbuf = buffer; - for( v = 0; v < vid.height;v++) + if( swblit.bpp == 2 ) + { + unsigned short *pbuf = buffer; + for( v = 0; v < 10;v++) + { + uint start = vid.rowbytes * v; + uint dstart = swblit.stride * v; + + for( u = 0; u < vid.width; u++ ) + { + unsigned int s = vid.screen[vid.buffer[start + u]]; + pbuf[dstart + u] = s; + } + } + } + else if( swblit.bpp == 4 ) { - uint start = vid.rowbytes * v; - uint dstart = swblit.stride * v; + unsigned int *pbuf = buffer; - for( u = 0; u < vid.width; u++ ) + for( v = 0; v < vid.height;v++) + { + uint start = vid.rowbytes * v; + uint dstart = swblit.stride * v; + + for( u = 0; u < vid.width; u++ ) + { + unsigned int s = vid.screen32[vid.buffer[start + u]]; + pbuf[dstart + u] = s; + } + } + } + else if( swblit.bpp == 3 ) + { + byte *pbuf = buffer; + for( v = 0; v < 10;v++) { - unsigned int s = vid.screen32[vid.buffer[start + u]]; - pbuf[(dstart+u)*3] = s; - s = s >> 8; - pbuf[(dstart+u)*3+1] = s; - s = s >> 8; - pbuf[(dstart+u)*3+2] = s; + uint start = vid.rowbytes * v; + uint dstart = swblit.stride * v; + + for( u = 0; u < vid.width; u++ ) + { + unsigned int s = vid.screen32[vid.buffer[start + u]]; + pbuf[(dstart+u)*3] = s; + s = s >> 8; + pbuf[(dstart+u)*3+1] = s; + s = s >> 8; + pbuf[(dstart+u)*3+2] = s; + } } } } swblit.pUnlockBuffer(); +// gEngfuncs.Con_Printf("blit end\n"); } diff --git a/r_local.h b/r_local.h index 893157ff..63e1a562 100644 --- a/r_local.h +++ b/r_local.h @@ -1241,6 +1241,7 @@ void R_DrawBrushModel(cl_entity_t *pent); void R_InitCaches (void); void R_BlitScreen( void ); void R_InitBlit( qboolean gl ); +qboolean R_SetDisplayTransform( uint rotate, int offset_x, int offset_y, float scale_x, float scale_y ); // // r_edge.c diff --git a/r_main.c b/r_main.c index ae11f3b4..38bcd72d 100644 --- a/r_main.c +++ b/r_main.c @@ -1871,7 +1871,7 @@ void GAME_EXPORT R_NewMap (void) } else { - auxedges = malloc (r_numallocatededges * sizeof(edge_t)); + auxedges = Mem_Malloc (r_temppool, r_numallocatededges * sizeof(edge_t) ); } // clear out efrags in case the level hasn't been reloaded From 609235b4f1548a91cbf417465a6ef05ccb07b735 Mon Sep 17 00:00:00 2001 From: mittorn Date: Thu, 31 Oct 2019 01:52:38 +0700 Subject: [PATCH 103/115] ref_soft: fix texcoords on image blitting --- r_draw.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/r_draw.c b/r_draw.c index 3525e6b2..6515169d 100644 --- a/r_draw.c +++ b/r_draw.c @@ -63,7 +63,7 @@ int GAME_EXPORT R_GetSpriteTexture( const model_t *m_pSpriteModel, int frame ) Draw_StretchPicImplementation ============= */ -void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, int s2, int t2, image_t *pic) +void R_DrawStretchPicImplementation( int x, int y, int w, int h, int s1, int t1, int s2, int t2, image_t *pic ) { pixel_t *source, *dest; unsigned int v, u, sv; @@ -127,9 +127,8 @@ void R_DrawStretchPicImplementation (int x, int y, int w, int h, int s1, int t1, { f = 0; - fstep = s2*0x10000/w; - if( w == s2 - s1 ) - fstep = 0x10000; + fstep = ((s2-s1) << 16)/w; + #if 0 for (u=0 ; uwidth, height = pic->height; // GL_Bind( XASH_TEXTURE0, texnum ); - if( s2 > 1 || t2 > 2 ) + if( s2 > 1.0f || t2 > 1.0f ) + return; + if( s1 < 0.0f || t1 < 0.0f ) return; - if( w <= 0 || h <= 0 ) + if( w < 1.0f || h < 1.0f ) return; - R_DrawStretchPicImplementation(x,y,w,h, pic->width * s1, pic->height * t1, pic->width * s2, pic->height * t2, pic); + R_DrawStretchPicImplementation(x,y,w,h, width * s1, height * t1, width * s2, height * t2, pic); } void Draw_Fill (int x, int y, int w, int h) From 26b8a1fe1d91ff638fd6b9dbf8493e5c44e8abc0 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sat, 2 Nov 2019 04:44:37 +0300 Subject: [PATCH 104/115] ref_soft: blit: restore height for bpp 16 and 32 --- r_glblit.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/r_glblit.c b/r_glblit.c index d9a6c169..6d97c815 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -661,7 +661,7 @@ void R_BlitScreen( void ) if( swblit.bpp == 2 ) { unsigned short *pbuf = buffer; - for( v = 0; v < 10;v++) + for( v = 0; v < vid.height;v++) { uint start = vid.rowbytes * v; uint d = swblit.stride - v - 1; @@ -694,7 +694,7 @@ void R_BlitScreen( void ) else if( swblit.bpp == 3 ) { byte *pbuf = buffer; - for( v = 0; v < 10;v++) + for( v = 0; v < vid.height;v++) { uint start = vid.rowbytes * v; uint d = swblit.stride - v - 1; @@ -717,7 +717,7 @@ void R_BlitScreen( void ) if( swblit.bpp == 2 ) { unsigned short *pbuf = buffer; - for( v = 0; v < 10;v++) + for( v = 0; v < vid.height;v++) { uint start = vid.rowbytes * v; uint dstart = swblit.stride * v; @@ -748,7 +748,7 @@ void R_BlitScreen( void ) else if( swblit.bpp == 3 ) { byte *pbuf = buffer; - for( v = 0; v < 10;v++) + for( v = 0; v < vid.height;v++) { uint start = vid.rowbytes * v; uint dstart = swblit.stride * v; From 3589537147278f878858b26e28ebb51cf3b25edc Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 2 Nov 2019 12:43:45 +0700 Subject: [PATCH 105/115] ref_soft: lowmemory: use ushort for r_leafkeys --- r_bsp.c | 5 ++++- r_local.h | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/r_bsp.c b/r_bsp.c index a141ba5f..816bf538 100644 --- a/r_bsp.c +++ b/r_bsp.c @@ -773,8 +773,11 @@ void R_DrawSubmodelPolygons (model_t *pmodel, int clipflags, mnode_t *topnode) int c_drawnode; +#if XASH_LOW_MEMORY +unsigned short r_leafkeys[MAX_MAP_LEAFS]; +#else int r_leafkeys[MAX_MAP_LEAFS]; - +#endif /* ================ R_RecursiveWorldNode diff --git a/r_local.h b/r_local.h index 63e1a562..ea2542c6 100644 --- a/r_local.h +++ b/r_local.h @@ -1201,8 +1201,11 @@ extern int r_currentbkey; extern qboolean insubmodel; extern vec3_t r_entorigin; - +#if XASH_LOW_MEMORY +extern unsigned short r_leafkeys[MAX_MAP_LEAFS]; +#else extern int r_leafkeys[MAX_MAP_LEAFS]; +#endif #define LEAF_KEY(pleaf) r_leafkeys[(pleaf - WORLDMODEL->leafs)] From a3a0db447bef3f2de1a19d11cc8a84c4278b323b Mon Sep 17 00:00:00 2001 From: mittorn Date: Sun, 3 Nov 2019 19:09:41 +0700 Subject: [PATCH 106/115] ref_soft: draw: check screen bounds in Draw_Fill --- r_draw.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/r_draw.c b/r_draw.c index 6515169d..24ff99f7 100644 --- a/r_draw.c +++ b/r_draw.c @@ -216,12 +216,20 @@ void Draw_Fill (int x, int y, int w, int h) if( x + w > vid.width ) w = vid.width - x; + if( w <= 0 ) + return; + if( y + h > vid.height ) h = vid.height - y; + if( h <= 0 ) + return; + height = h; - if (y < 0) + if( y < 0 ) { + if( h <= -y ) + return; skip = -y; height += y; y = 0; From d1af73bfcb216f478e94438df17ff9bb7066a1a3 Mon Sep 17 00:00:00 2001 From: mittorn Date: Mon, 4 Nov 2019 22:11:11 +0700 Subject: [PATCH 107/115] ref_soft: image: fix wrong alpha buffer --- r_image.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/r_image.c b/r_image.c index 568fbbc9..fccde428 100644 --- a/r_image.c +++ b/r_image.c @@ -529,7 +529,7 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) uint width, height; uint i, j, numSides; uint offset = 0; - qboolean normalMap; + qboolean normalMap = false; const byte *bufend; int mipCount; @@ -553,7 +553,7 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) mipCount = 4;//GL_CalcMipmapCount( tex, ( buf != NULL )); // NOTE: only single uncompressed textures can be resamples, no mips, no layers, no sides - if(( tex->depth == 1 ) && (( pic->width != tex->width ) || ( pic->height != tex->height ))) + if((( pic->width != tex->width ) || ( pic->height != tex->height ))) data = GL_ResampleTexture( buf, pic->width, pic->height, tex->width, tex->height, normalMap ); else data = buf; @@ -603,9 +603,9 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) tex->pixels[j][i] = major << 8 | (minor & 0xFF); if( j == 0 && tex->alpha_pixels ) { - unsigned int alpha = (pic->buffer[i * 4 + 3] * 8 / 256) << (16 - 3); + unsigned int alpha = (data[i * 4 + 3] * 8 / 256) << (16 - 3); tex->alpha_pixels[i] = (tex->pixels[j][i] >> 3) | alpha; - if( !sw_noalphabrushes->value && pic->buffer[i * 4 + 3] < 128 && FBitSet( pic->flags, IMAGE_ONEBIT_ALPHA ) ) + if( !sw_noalphabrushes->value && data[i * 4 + 3] < 128 && FBitSet( pic->flags, IMAGE_ONEBIT_ALPHA ) ) tex->pixels[j][i] = TRANSPARENT_COLOR; //0000 0011 0100 1001; } From ef270eb642a99b8629f81f2c8c3aaad301357e68 Mon Sep 17 00:00:00 2001 From: mittorn Date: Mon, 4 Nov 2019 22:12:09 +0700 Subject: [PATCH 108/115] ref_soft: update ref api --- r_glblit.c | 2 +- r_local.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/r_glblit.c b/r_glblit.c index 6d97c815..4a50f3d8 100644 --- a/r_glblit.c +++ b/r_glblit.c @@ -13,7 +13,7 @@ struct swblit_s } swblit; -qboolean R_SetDisplayTransform( uint rotate, int offset_x, int offset_y, float scale_x, float scale_y ) +qboolean R_SetDisplayTransform( ref_screen_rotation_t rotate, int offset_x, int offset_y, float scale_x, float scale_y ) { qboolean ret = true; if( rotate > 1 ) diff --git a/r_local.h b/r_local.h index ea2542c6..fc91a4ef 100644 --- a/r_local.h +++ b/r_local.h @@ -1244,7 +1244,7 @@ void R_DrawBrushModel(cl_entity_t *pent); void R_InitCaches (void); void R_BlitScreen( void ); void R_InitBlit( qboolean gl ); -qboolean R_SetDisplayTransform( uint rotate, int offset_x, int offset_y, float scale_x, float scale_y ); +qboolean R_SetDisplayTransform( ref_screen_rotation_t rotate, int offset_x, int offset_y, float scale_x, float scale_y ); // // r_edge.c From d4efb554924531335375e84184d55acf083e7313 Mon Sep 17 00:00:00 2001 From: mittorn Date: Mon, 4 Nov 2019 22:39:22 +0700 Subject: [PATCH 109/115] ref_soft: lowmemory: prevent redefines --- r_local.h | 2 ++ r_studio.c | 13 +++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/r_local.h b/r_local.h index fc91a4ef..d31bc462 100644 --- a/r_local.h +++ b/r_local.h @@ -64,6 +64,8 @@ extern byte *r_temppool; #define MAX_DECAL_SURFS 4096 #if XASH_LOW_MEMORY + #undef MAX_TEXTURES + #undef MAX_DECAL_SURFS #define MAX_TEXTURES 1024 #define MAX_DECAL_SURFS 256 #endif diff --git a/r_studio.c b/r_studio.c index 807bcab3..557f1f09 100644 --- a/r_studio.c +++ b/r_studio.c @@ -57,6 +57,7 @@ typedef struct sortedmesh_s } sortedmesh_t; #if XASH_LOW_MEMORY + #undef MAXSTUDIOVERTS #define MAXSTUDIOVERTS 1024 #endif @@ -3527,7 +3528,7 @@ static void R_StudioLoadTexture( model_t *mod, studiohdr_t *phdr, mstudiotexture int flags = 0; char texname[128], name[128], mdlname[128]; texture_t *tx = NULL; - + if( ptexture->flags & STUDIO_NF_NORMALMAP ) flags |= (TF_NORMALMAP); @@ -3551,17 +3552,17 @@ static void R_StudioLoadTexture( model_t *mod, studiohdr_t *phdr, mstudiotexture tx->anim_min = PLATE_HUE_START; // topcolor start tx->anim_max = PLATE_HUE_END; // topcolor end // bottomcolor start always equal is (topcolor end + 1) - tx->anim_total = SUIT_HUE_END;// bottomcolor end + tx->anim_total = SUIT_HUE_END;// bottomcolor end } else { Q_strncpy( tx->name, "DM_User", sizeof( tx->name )); // custom remapped - Q_strncpy( val, ptexture->name + 7, 4 ); + Q_strncpy( val, ptexture->name + 7, 4 ); tx->anim_min = bound( 0, Q_atoi( val ), 255 ); // topcolor start - Q_strncpy( val, ptexture->name + 11, 4 ); + Q_strncpy( val, ptexture->name + 11, 4 ); tx->anim_max = bound( 0, Q_atoi( val ), 255 ); // topcolor end // bottomcolor start always equal is (topcolor end + 1) - Q_strncpy( val, ptexture->name + 15, 4 ); + Q_strncpy( val, ptexture->name + 15, 4 ); tx->anim_total = bound( 0, Q_atoi( val ), 255 ); // bottomcolor end } @@ -3603,7 +3604,7 @@ static void R_StudioLoadTexture( model_t *mod, studiohdr_t *phdr, mstudiotexture } else if( tx ) { - // duplicate texnum for easy acess + // duplicate texnum for easy acess tx->gl_texturenum = ptexture->index; } } From 59f053b1dba1fca3cbb77bdffbcd71071707afea Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 25 Jan 2020 15:54:56 +0700 Subject: [PATCH 110/115] ref_soft: fix Werrors --- r_context.c | 2 +- r_image.c | 4 ++-- r_local.h | 4 ++-- r_main.c | 2 +- r_polyse.c | 4 ++-- r_studio.c | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/r_context.c b/r_context.c index a576492d..6f350bbc 100644 --- a/r_context.c +++ b/r_context.c @@ -309,7 +309,7 @@ void GAME_EXPORT R_ProcessEntData( qboolean allocate ) // stubs -void GAME_EXPORT GL_SetTexCoordArrayMode( void ) +void GAME_EXPORT GL_SetTexCoordArrayMode( uint mode ) { } diff --git a/r_image.c b/r_image.c index fccde428..b4f353f2 100644 --- a/r_image.c +++ b/r_image.c @@ -572,14 +572,14 @@ static qboolean GL_UploadTexture( image_t *tex, rgbdata_t *pic ) // increase size to workaround triangle renderer bugs // it seems to assume memory readable. maybe it was pointed to WAD? //tex->pixels[j] = (byte*)Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) + 1024 ) + 512; - tex->pixels[j] = (byte*)Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) ); + tex->pixels[j] = (pixel_t*)Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) ); //memset( (byte*)tex->pixels[j] - 512, 0xFF, 512 ); //memset( (byte*)tex->pixels[j] + width * height * sizeof(pixel_t), 0xFF, 512 ); if( j == 0 && tex->flags & TF_HAS_ALPHA ) - tex->alpha_pixels = (byte*)Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) ); + tex->alpha_pixels = (pixel_t*)Mem_Calloc( r_temppool, width * height * sizeof(pixel_t) ); for(i = 0; i < height * width; i++ ) { diff --git a/r_local.h b/r_local.h index d31bc462..67411b56 100644 --- a/r_local.h +++ b/r_local.h @@ -363,7 +363,7 @@ typedef struct image_s int servercount; uint hashValue; - struct gltexture_s *nextHash; + struct image_s *nextHash; } image_t; #if 0 @@ -956,7 +956,7 @@ typedef struct typedef struct { - byte *surfdat; // destination for generated surface + pixel_t *surfdat; // destination for generated surface int rowbytes; // destination logical width in bytes msurface_t *surf; // description for surface to generate fixed8_t lightadj[MAXLIGHTMAPS]; diff --git a/r_main.c b/r_main.c index 38bcd72d..2702736f 100644 --- a/r_main.c +++ b/r_main.c @@ -637,7 +637,7 @@ static void R_SetupFrame( void ) // if( !gl_nosort->value ) { // sort translucents entities by rendermode and distance - qsort( tr.draw_list->trans_entities, tr.draw_list->num_trans_entities, sizeof( cl_entity_t* ), R_TransEntityCompare ); + qsort( tr.draw_list->trans_entities, tr.draw_list->num_trans_entities, sizeof( cl_entity_t* ), (void*)R_TransEntityCompare ); } // current viewleaf diff --git a/r_polyse.c b/r_polyse.c index e987f33d..e1038f4d 100644 --- a/r_polyse.c +++ b/r_polyse.c @@ -1423,8 +1423,8 @@ void R_PolysetDrawSpans8_Opaque (spanpackage_t *pspanpackage) if (lcount) { int lsfrac, ltfrac; - byte *lpdest; - byte *lptex; + pixel_t *lpdest; + pixel_t *lptex; int llight; int lzi; short *lpz; diff --git a/r_studio.c b/r_studio.c index 557f1f09..de4197f7 100644 --- a/r_studio.c +++ b/r_studio.c @@ -2159,7 +2159,7 @@ static void R_StudioDrawPoints( void ) if( r_studio_sort_textures->value && need_sort ) { // resort opaque and translucent meshes draw order - qsort( g_studio.meshes, m_pSubModel->nummesh, sizeof( sortedmesh_t ), R_StudioMeshCompare ); + qsort( g_studio.meshes, m_pSubModel->nummesh, sizeof( sortedmesh_t ), (void*)R_StudioMeshCompare ); } // NOTE: rewind normals at start @@ -2880,7 +2880,7 @@ void R_StudioRenderFinal( void ) { for( i = 0; i < m_pStudioHeader->numbodyparts; i++ ) { - R_StudioSetupModel( i, &m_pBodyPart, &m_pSubModel ); + R_StudioSetupModel( i, (void*)&m_pBodyPart, (void*)&m_pSubModel ); GL_StudioSetRenderMode( rendermode ); R_StudioDrawPoints(); From 4c7e19adeb686b9f979c5c35c69f91b765695bc5 Mon Sep 17 00:00:00 2001 From: mittorn Date: Sat, 25 Jan 2020 21:57:49 +0700 Subject: [PATCH 111/115] ref_soft: fix unaligned access --- r_sprite.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/r_sprite.c b/r_sprite.c index 512c06f3..2a867c80 100644 --- a/r_sprite.c +++ b/r_sprite.c @@ -53,13 +53,14 @@ upload a single frame */ static dframetype_t *R_SpriteLoadFrame( model_t *mod, void *pin, mspriteframe_t **ppframe, int num ) { - dspriteframe_t *pinframe; + dspriteframe_t pinframe; mspriteframe_t *pspriteframe; int gl_texturenum = 0; char texname[128]; int bytes = 1; - pinframe = (dspriteframe_t *)pin; + memcpy( &pinframe, pin, sizeof( dspriteframe_t ) ); + if( sprite_version == SPRITE_VERSION_32 ) bytes = 4; @@ -67,26 +68,26 @@ static dframetype_t *R_SpriteLoadFrame( model_t *mod, void *pin, mspriteframe_t if( FBitSet( mod->flags, MODEL_CLIENT )) // it's a HUD sprite { Q_snprintf( texname, sizeof( texname ), "#HUD/%s(%s:%i%i).spr", sprite_name, group_suffix, num / 10, num % 10 ); - gl_texturenum = GL_LoadTexture( texname, pin, pinframe->width * pinframe->height * bytes, r_texFlags ); + gl_texturenum = GL_LoadTexture( texname, pin, pinframe.width * pinframe.height * bytes, r_texFlags ); } else { Q_snprintf( texname, sizeof( texname ), "#%s(%s:%i%i).spr", sprite_name, group_suffix, num / 10, num % 10 ); - gl_texturenum = GL_LoadTexture( texname, pin, pinframe->width * pinframe->height * bytes, r_texFlags ); + gl_texturenum = GL_LoadTexture( texname, pin, pinframe.width * pinframe.height * bytes, r_texFlags ); } // setup frame description pspriteframe = Mem_Malloc( mod->mempool, sizeof( mspriteframe_t )); - pspriteframe->width = pinframe->width; - pspriteframe->height = pinframe->height; - pspriteframe->up = pinframe->origin[1]; - pspriteframe->left = pinframe->origin[0]; - pspriteframe->down = pinframe->origin[1] - pinframe->height; - pspriteframe->right = pinframe->width + pinframe->origin[0]; + pspriteframe->width = pinframe.width; + pspriteframe->height = pinframe.height; + pspriteframe->up = pinframe.origin[1]; + pspriteframe->left = pinframe.origin[0]; + pspriteframe->down = pinframe.origin[1] - pinframe.height; + pspriteframe->right = pinframe.width + pinframe.origin[0]; pspriteframe->gl_texturenum = gl_texturenum; *ppframe = pspriteframe; - return (dframetype_t *)((byte *)(pinframe + 1) + pinframe->width * pinframe->height * bytes ); + return ( pin + sizeof(dspriteframe_t) + pinframe.width * pinframe.height * bytes ); } /* From b81345f063e4dff371ee6f709f4850757a34a911 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sat, 28 Mar 2020 21:56:08 +0300 Subject: [PATCH 112/115] ref_soft: add some cvars to GLCONFIG, so they would be saved into ref_soft.cfg and fix UB in cast --- r_main.c | 14 +++++++------- r_studio.c | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/r_main.c b/r_main.c index 2702736f..fb37e0f9 100644 --- a/r_main.c +++ b/r_main.c @@ -1933,7 +1933,6 @@ qboolean GAME_EXPORT R_Init( void ) r_drawentities = gEngfuncs.Cvar_Get( "r_drawentities", "1", FCVAR_CHEAT, "render entities" ); vid_brightness = gEngfuncs.pfnGetCvarPointer( "brightness", 0 ); r_fullbright = gEngfuncs.Cvar_Get( "r_fullbright", "0", FCVAR_CHEAT, "disable lightmaps, get fullbright for entities" ); - sw_mipcap = gEngfuncs.Cvar_Get( "r_fullbright", "0", FCVAR_CHEAT, "disable lightmaps, get fullbright for entities" ); r_dynamic = gEngfuncs.Cvar_Get( "r_dynamic", "1", FCVAR_ARCHIVE, "allow dynamic lighting (dlights, lightstyles)" ); r_lightmap = gEngfuncs.Cvar_Get( "r_lightmap", "0", FCVAR_CHEAT, "lightmap debugging tool" ); @@ -1945,17 +1944,18 @@ qboolean GAME_EXPORT R_Init( void ) sw_draworder = gEngfuncs.Cvar_Get ("sw_draworder", "0", 0, ""); sw_maxedges = gEngfuncs.Cvar_Get ("sw_maxedges", "32", 0, ""); sw_maxsurfs = gEngfuncs.Cvar_Get ("sw_maxsurfs", "0", 0, ""); - sw_mipscale = gEngfuncs.Cvar_Get ("sw_mipscale", "1", 0, ""); + sw_mipscale = gEngfuncs.Cvar_Get ("sw_mipscale", "1", FCVAR_GLCONFIG, "nothing"); + sw_mipcap = gEngfuncs.Cvar_Get( "sw_mipcap", "0", FCVAR_GLCONFIG, "nothing" ); sw_reportedgeout = gEngfuncs.Cvar_Get ("sw_reportedgeout", "0", 0, ""); sw_reportsurfout = gEngfuncs.Cvar_Get ("sw_reportsurfout", "0", 0, ""); - sw_stipplealpha = gEngfuncs.Cvar_Get( "sw_stipplealpha", "1", FCVAR_ARCHIVE, "" ); + sw_stipplealpha = gEngfuncs.Cvar_Get( "sw_stipplealpha", "1", FCVAR_GLCONFIG, "nothing" ); sw_surfcacheoverride = gEngfuncs.Cvar_Get ("sw_surfcacheoverride", "0", 0, ""); - sw_waterwarp = gEngfuncs.Cvar_Get ("sw_waterwarp", "1", 0, ""); - sw_notransbrushes = gEngfuncs.Cvar_Get( "sw_notransbrushes", "0", FCVAR_ARCHIVE, "do not apply transparency to water/glasses (faster)"); - sw_noalphabrushes = gEngfuncs.Cvar_Get( "sw_noalphabrushes", "0", FCVAR_ARCHIVE, "do not draw brush holes (faster)"); + sw_waterwarp = gEngfuncs.Cvar_Get ("sw_waterwarp", "1", FCVAR_GLCONFIG, "nothing"); + sw_notransbrushes = gEngfuncs.Cvar_Get( "sw_notransbrushes", "0", FCVAR_GLCONFIG, "do not apply transparency to water/glasses (faster)"); + sw_noalphabrushes = gEngfuncs.Cvar_Get( "sw_noalphabrushes", "0", FCVAR_GLCONFIG, "do not draw brush holes (faster)"); r_traceglow = gEngfuncs.Cvar_Get( "r_traceglow", "1", FCVAR_ARCHIVE, "cull flares behind models" ); #ifndef DISABLE_TEXFILTER - sw_texfilt = gEngfuncs.Cvar_Get ("sw_texfilt", "0", 0, "texture dither"); + sw_texfilt = gEngfuncs.Cvar_Get ("sw_texfilt", "0", FCVAR_GLCONFIG, "texture dither"); #endif //r_lefthand = ri.Cvar_Get( "hand", "0", FCVAR_USERINFO | FCVAR_ARCHIVE ); // r_speeds = ri.Cvar_Get ("r_speeds", "0", 0); diff --git a/r_studio.c b/r_studio.c index de4197f7..620788e1 100644 --- a/r_studio.c +++ b/r_studio.c @@ -2880,7 +2880,7 @@ void R_StudioRenderFinal( void ) { for( i = 0; i < m_pStudioHeader->numbodyparts; i++ ) { - R_StudioSetupModel( i, (void*)&m_pBodyPart, (void*)&m_pSubModel ); + R_StudioSetupModel( i, (void**)&m_pBodyPart, (void**)&m_pSubModel ); GL_StudioSetRenderMode( rendermode ); R_StudioDrawPoints(); From 237d6f86898e2c96b820f772c54916fc3cf76f4b Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sun, 29 Mar 2020 16:58:27 +0300 Subject: [PATCH 113/115] ref_soft: upgrade to latest RefAPI version --- r_context.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/r_context.c b/r_context.c index 6f350bbc..d81123b2 100644 --- a/r_context.c +++ b/r_context.c @@ -428,6 +428,11 @@ const char *R_GetConfigName( void ) return "ref_soft"; // software specific cvars will go to ref_soft.cfg } +static void* GAME_EXPORT R_GetProcAddress( const char *name ) +{ + return gEngfuncs.GL_GetProcAddress( name ); +} + ref_interface_t gReffuncs = { R_Init, @@ -544,6 +549,7 @@ ref_interface_t gReffuncs = Mod_GetCurrentVis, R_NewMap, R_ClearScene, + R_GetProcAddress, TriRenderMode, TriBegin, From 3984a5802576821d87d6a948ee86aa192ea5c891 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sun, 29 Mar 2020 17:01:45 +0300 Subject: [PATCH 114/115] ref_soft: upgrade to latest RefAPI and libpublic --- r_light.c | 2 +- r_local.h | 2 +- r_main.c | 2 +- r_math.c | 2 +- r_studio.c | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/r_light.c b/r_light.c index 8f292e29..4d4f9c84 100644 --- a/r_light.c +++ b/r_light.c @@ -16,7 +16,7 @@ GNU General Public License for more details. #include "r_local.h" #include "pm_local.h" #include "studio.h" -#include "mathlib.h" +#include "xash3d_mathlib.h" #include "ref_params.h" //unused, need refactor diff --git a/r_local.h b/r_local.h index 67411b56..36d34580 100644 --- a/r_local.h +++ b/r_local.h @@ -25,7 +25,7 @@ GNU General Public License for more details. #include "protocol.h" #include "dlight.h" #include "ref_api.h" -#include "mathlib.h" +#include "xash3d_mathlib.h" #include "ref_params.h" #include "enginefeatures.h" #include "com_strings.h" diff --git a/r_main.c b/r_main.c index fb37e0f9..a67d039d 100644 --- a/r_main.c +++ b/r_main.c @@ -14,7 +14,7 @@ GNU General Public License for more details. */ #include "r_local.h" -#include "mathlib.h" +#include "xash3d_mathlib.h" #include "library.h" //#include "beamdef.h" //#include "particledef.h" diff --git a/r_math.c b/r_math.c index f8a43d7f..4c835623 100644 --- a/r_math.c +++ b/r_math.c @@ -14,7 +14,7 @@ GNU General Public License for more details. */ #include "r_local.h" -#include "mathlib.h" +#include "xash3d_mathlib.h" /* ======================================================================== diff --git a/r_studio.c b/r_studio.c index 620788e1..6510fd85 100644 --- a/r_studio.c +++ b/r_studio.c @@ -14,7 +14,7 @@ GNU General Public License for more details. */ #include "r_local.h" -#include "mathlib.h" +#include "xash3d_mathlib.h" #include "const.h" #include "r_studioint.h" #include "triangleapi.h" @@ -2432,11 +2432,11 @@ R_StudioSetRemapColors */ static void R_StudioSetRemapColors( int newTop, int newBottom ) { - gEngfuncs.CL_AllocRemapInfo( newTop, newBottom ); + gEngfuncs.CL_AllocRemapInfo( RI.currententity, newTop, newBottom ); if( gEngfuncs.CL_GetRemapInfoForEntity( RI.currententity )) { - gEngfuncs.CL_UpdateRemapInfo( newTop, newBottom ); + gEngfuncs.CL_UpdateRemapInfo( RI.currententity, newTop, newBottom ); m_fDoRemap = true; } } From 9045657352c7dfd3622cdf2b69462ca33f4262ee Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sun, 29 Mar 2020 17:02:06 +0300 Subject: [PATCH 115/115] ref_soft: sprite: fix to compile(copypasted from ref_gl) --- r_sprite.c | 57 ++++++++++++++++++++++++++---------------------------- 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/r_sprite.c b/r_sprite.c index 2a867c80..a512a27a 100644 --- a/r_sprite.c +++ b/r_sprite.c @@ -51,7 +51,7 @@ R_SpriteLoadFrame upload a single frame ==================== */ -static dframetype_t *R_SpriteLoadFrame( model_t *mod, void *pin, mspriteframe_t **ppframe, int num ) +static const dframetype_t *R_SpriteLoadFrame( model_t *mod, const void *pin, mspriteframe_t **ppframe, int num ) { dspriteframe_t pinframe; mspriteframe_t *pspriteframe; @@ -59,7 +59,7 @@ static dframetype_t *R_SpriteLoadFrame( model_t *mod, void *pin, mspriteframe_t char texname[128]; int bytes = 1; - memcpy( &pinframe, pin, sizeof( dspriteframe_t ) ); + memcpy( &pinframe, pin, sizeof(dspriteframe_t)); if( sprite_version == SPRITE_VERSION_32 ) bytes = 4; @@ -74,7 +74,7 @@ static dframetype_t *R_SpriteLoadFrame( model_t *mod, void *pin, mspriteframe_t { Q_snprintf( texname, sizeof( texname ), "#%s(%s:%i%i).spr", sprite_name, group_suffix, num / 10, num % 10 ); gl_texturenum = GL_LoadTexture( texname, pin, pinframe.width * pinframe.height * bytes, r_texFlags ); - } + } // setup frame description pspriteframe = Mem_Malloc( mod->mempool, sizeof( mspriteframe_t )); @@ -87,7 +87,7 @@ static dframetype_t *R_SpriteLoadFrame( model_t *mod, void *pin, mspriteframe_t pspriteframe->gl_texturenum = gl_texturenum; *ppframe = pspriteframe; - return ( pin + sizeof(dspriteframe_t) + pinframe.width * pinframe.height * bytes ); + return ( const dframetype_t* )(( const byte* )pin + sizeof( dspriteframe_t ) + pinframe.width * pinframe.height * bytes ); } /* @@ -97,16 +97,16 @@ R_SpriteLoadGroup upload a group frames ==================== */ -static dframetype_t *R_SpriteLoadGroup( model_t *mod, void *pin, mspriteframe_t **ppframe, int framenum ) +static const dframetype_t *R_SpriteLoadGroup( model_t *mod, const void *pin, mspriteframe_t **ppframe, int framenum ) { - dspritegroup_t *pingroup; + const dspritegroup_t *pingroup; mspritegroup_t *pspritegroup; - dspriteinterval_t *pin_intervals; + const dspriteinterval_t *pin_intervals; float *poutintervals; int i, groupsize, numframes; - void *ptemp; + const void *ptemp; - pingroup = (dspritegroup_t *)pin; + pingroup = (const dspritegroup_t *)pin; numframes = pingroup->numframes; groupsize = sizeof( mspritegroup_t ) + (numframes - 1) * sizeof( pspritegroup->frames[0] ); @@ -114,7 +114,7 @@ static dframetype_t *R_SpriteLoadGroup( model_t *mod, void *pin, mspriteframe_t pspritegroup->numframes = numframes; *ppframe = (mspriteframe_t *)pspritegroup; - pin_intervals = (dspriteinterval_t *)(pingroup + 1); + pin_intervals = (const dspriteinterval_t *)(pingroup + 1); poutintervals = Mem_Calloc( mod->mempool, numframes * sizeof( float )); pspritegroup->intervals = poutintervals; @@ -127,13 +127,13 @@ static dframetype_t *R_SpriteLoadGroup( model_t *mod, void *pin, mspriteframe_t pin_intervals++; } - ptemp = (void *)pin_intervals; + ptemp = (const void *)pin_intervals; for( i = 0; i < numframes; i++ ) { ptemp = R_SpriteLoadFrame( mod, ptemp, &pspritegroup->frames[i], framenum * 10 + i ); } - return (dframetype_t *)ptemp; + return (const dframetype_t *)ptemp; } /* @@ -167,7 +167,7 @@ void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, ui if( numi == NULL ) { rgbdata_t *pal; - + pal = gEngfuncs.FS_LoadImage( "#id.pal", (byte *)&i, 768 ); pframetype = (const dframetype_t *)((const byte*)buffer + sizeof( dsprite_q1_t )); // pinq1 + 1 gEngfuncs.FS_FreeImage( pal ); // palette installed, no reason to keep this data @@ -194,7 +194,7 @@ void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, ui pframetype = (const dframetype_t *)(src + 768); gEngfuncs.FS_FreeImage( pal ); // palette installed, no reason to keep this data } - else + else { gEngfuncs.Con_DPrintf( S_ERROR "%s has wrong number of palette colors %i (should be 256)\n", mod->name, *numi ); return; @@ -206,7 +206,7 @@ void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, ui for( i = 0; i < mod->numframes; i++ ) { frametype_t frametype = pframetype->type; - psprite->frames[i].type = frametype; + psprite->frames[i].type = (spriteframetype_t)frametype; switch( frametype ) { @@ -237,7 +237,7 @@ Loading a bitmap image as sprite with multiple frames as pieces of input image ==================== */ -void GAME_EXPORT Mod_LoadMapSprite( model_t *mod, const void *buffer, size_t size, qboolean *loaded ) +void Mod_LoadMapSprite( model_t *mod, const void *buffer, size_t size, qboolean *loaded ) { byte *src, *dst; rgbdata_t *pix, temp; @@ -360,7 +360,7 @@ release sprite model and frames void Mod_SpriteUnloadTextures( void *data ) { msprite_t *psprite; - mspritegroup_t *pspritegroup; + mspritegroup_t *pspritegroup; mspriteframe_t *pspriteframe; int i, j; @@ -424,7 +424,7 @@ mspriteframe_t *R_GetSpriteFrame( const model_t *pModel, int frame, float yaw ) { pspriteframe = psprite->frames[frame].frameptr; } - else if( psprite->frames[frame].type == SPR_GROUP ) + else if( psprite->frames[frame].type == SPR_GROUP ) { pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; pintervals = pspritegroup->intervals; @@ -481,7 +481,7 @@ float R_GetSpriteFrameInterpolant( cl_entity_t *ent, mspriteframe_t **oldframe, if( frame < 0 ) { frame = 0; - } + } else if( frame >= psprite->numframes ) { gEngfuncs.Con_Reportf( S_WARN "R_GetSpriteFrameInterpolant: no such frame %d (%s)\n", frame, ent->model->name ); @@ -500,7 +500,7 @@ float R_GetSpriteFrameInterpolant( cl_entity_t *ent, mspriteframe_t **oldframe, ent->latched.sequencetime = gpGlobals->time; lerpFrac = 1.0f; } - + if( ent->latched.sequencetime < gpGlobals->time ) { if( frame != ent->latched.prevblending[1] ) @@ -537,7 +537,7 @@ float R_GetSpriteFrameInterpolant( cl_entity_t *ent, mspriteframe_t **oldframe, if( oldframe ) *oldframe = psprite->frames[ent->latched.prevblending[0]].frameptr; if( curframe ) *curframe = psprite->frames[frame].frameptr; } - else if( psprite->frames[frame].type == FRAME_GROUP ) + else if( psprite->frames[frame].type == FRAME_GROUP ) { pspritegroup = (mspritegroup_t *)psprite->frames[frame].frameptr; pintervals = pspritegroup->intervals; @@ -672,9 +672,7 @@ static float R_SpriteGlowBlend( vec3_t origin, int rendermode, int renderfx, flo tr = gEngfuncs.EV_VisTraceLine( RI.vieworg, origin, r_traceglow->value ? PM_GLASS_IGNORE : (PM_GLASS_IGNORE|PM_STUDIO_IGNORE)); if(( 1.0f - tr->fraction ) * dist > 8.0f ) - { return 0.0f; - } } if( renderfx == kRenderFxNoDissipation ) @@ -700,7 +698,6 @@ qboolean R_SpriteOccluded( cl_entity_t *e, vec3_t origin, float *pscale ) { float blend; vec3_t v; - //return false; TriWorldToScreen( origin, v ); @@ -721,7 +718,7 @@ qboolean R_SpriteOccluded( cl_entity_t *e, vec3_t origin, float *pscale ) return true; } - return false; + return false; } /* @@ -828,7 +825,7 @@ static qboolean R_SpriteHasLightmap( cl_entity_t *e, int texFormat ) { if( !r_sprite_lighting->value ) return false; - + if( texFormat != SPR_ALPHTEST ) return false; @@ -900,7 +897,7 @@ void R_DrawSpriteModel( cl_entity_t *e ) if( e->curstate.aiment > 0 && e->curstate.movetype == MOVETYPE_FOLLOW ) { cl_entity_t *parent; - + parent = gEngfuncs.GetEntityByIndex( e->curstate.aiment ); if( parent && parent->model ) @@ -967,7 +964,7 @@ void R_DrawSpriteModel( cl_entity_t *e ) color[1] = 1.0f; color[2] = 1.0f; } - + if( R_SpriteHasLightmap( e, psprite->texFormat )) { colorVec lightColor = R_LightPoint( origin ); @@ -1020,14 +1017,14 @@ void R_DrawSpriteModel( cl_entity_t *e ) break; case SPR_FWD_PARALLEL: // normal sprite default: - VectorCopy( RI.vright, v_right ); + VectorCopy( RI.vright, v_right ); VectorCopy( RI.vup, v_up ); break; } //if( psprite->facecull == SPR_CULL_NONE ) //GL_Cull( GL_NONE ); - + if( oldframe == frame ) { // draw the single non-lerped frame