diff --git a/CMakeLists.txt b/CMakeLists.txt index 4947258619..eb0da8aa40 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,10 +44,12 @@ option(BuildMPRend2 "Whether to create projects for the EXPERIMENTAL MP rend2 re option(BuildSPEngine "Whether to create projects for the SP engine (openjk_sp.exe)" ON) option(BuildSPGame "Whether to create projects for the SP gamecode (jagamex86.dll)" ON) option(BuildSPRdVanilla "Whether to create projects for the SP default renderer (rdsp-vanilla_x86.dll)" ON) +option(BuildSPRend2 "Whether to create projects for the EXPERIMENTAL SP rend2 renderer (rdsp-rend2_x86.dll)" ON) option(BuildJK2SPEngine "Whether to create projects for the jk2 SP engine (openjo_sp.exe)" OFF) option(BuildJK2SPGame "Whether to create projects for the jk2 sp gamecode mod (jk2gamex86.dll)" OFF) option(BuildJK2SPRdVanilla "Whether to create projects for the jk2 sp renderer (rdjosp-vanilla_x86.dll)" OFF) +option(BuildJK2SPRdRend2 "Whether to create projects for the EXPERIMENTAL jk2 SP rend2 renderer (rdjosp-rend2_x86.dll)" OFF) option(BuildTests "Whether to build automatic unit tests (requires Boost)" OFF) @@ -161,6 +163,7 @@ endif() set(SPEngine "openjk_sp.${Architecture}") set(SPGame "jagame${Architecture}") set(SPRDVanillaRenderer "rdsp-vanilla_${Architecture}") +set(SPRend2 "rdsp-rend2_${Architecture}") set(MPEngine "openjk.${Architecture}") set(MPVanillaRenderer "rd-vanilla_${Architecture}") set(MPDed "openjkded.${Architecture}") @@ -171,6 +174,7 @@ set(MPRend2 "rd-rend2_${Architecture}") set(JK2SPEngine "openjo_sp.${Architecture}") set(JK2SPGame "jospgame${Architecture}") set(JK2SPVanillaRenderer "rdjosp-vanilla_${Architecture}") +set(JK2SPRend2Renderer "rdjosp-rend2_${Architecture}") set(AssetsPk3 "openjk-${Architecture}.pk3") # Library names set(MPBotLib "botlib") diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index f41d0f7a2c..8b108f1a22 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -29,6 +29,11 @@ endif(BuildSPGame) # Add Modular Renderer project add_subdirectory("${SPDir}/rd-vanilla") +# Add rend2 JKA Renderer Project +if(BuildSPRend2 OR BuildJK2SPRdRend2) + add_subdirectory("${SPDir}/rd-rend2") +endif(BuildSPRend2 OR BuildJK2SPRdRend2) + # Add Engine Project if(BuildSPEngine OR BuildJK2SPEngine) # Libraries diff --git a/code/client/cl_cgame.cpp b/code/client/cl_cgame.cpp index b9d7b6fc11..c57c3ba010 100644 --- a/code/client/cl_cgame.cpp +++ b/code/client/cl_cgame.cpp @@ -1006,7 +1006,7 @@ intptr_t CL_CgameSystemCalls( intptr_t *args ) { case CG_R_GETLIGHTING: return re.GetLighting( (const float * ) VMA(1), (float *) VMA(2), (float *) VMA(3), (float *) VMA(4) ); case CG_R_ADDPOLYTOSCENE: - re.AddPolyToScene( args[1], args[2], (const polyVert_t *) VMA(3) ); + re.AddPolyToScene( args[1], args[2], (const polyVert_t *) VMA(3), 1 ); return 0; case CG_R_ADDLIGHTTOSCENE: re.AddLightToScene( (const float *) VMA(1), VMF(2), VMF(3), VMF(4), VMF(5) ); diff --git a/code/client/cl_cin.cpp b/code/client/cl_cin.cpp index 7cf2db8c2f..b2c34a74f8 100644 --- a/code/client/cl_cin.cpp +++ b/code/client/cl_cin.cpp @@ -1667,7 +1667,7 @@ static void CIN_AddTextCrawl() // render it out re.ClearScene(); - re.AddPolyToScene( cinTable[CL_handle].hCRAWLTEXT, 4, verts ); + re.AddPolyToScene( cinTable[CL_handle].hCRAWLTEXT, 4, verts, 1 ); re.RenderScene( &refdef ); //time's up diff --git a/code/client/cl_main.cpp b/code/client/cl_main.cpp index 1a5c244665..c213202dee 100644 --- a/code/client/cl_main.cpp +++ b/code/client/cl_main.cpp @@ -1055,11 +1055,6 @@ int get_com_frameTime( void ) return com_frameTime; } -void *CL_Malloc(int iSize, memtag_t eTag, qboolean bZeroit, int iAlign) -{ - return Z_Malloc(iSize, eTag, bZeroit); -} - /* ============ CL_InitRef @@ -1153,7 +1148,7 @@ void CL_InitRef( void ) { RIT(SV_Trace); RIT(S_RestartMusic); RIT(Z_Free); - rit.Malloc=CL_Malloc; + RIT(Z_Malloc); RIT(Z_MemSize); RIT(Z_MorphMallocTag); diff --git a/code/client/cl_ui.cpp b/code/client/cl_ui.cpp index 80d002f1f3..743aeb3381 100644 --- a/code/client/cl_ui.cpp +++ b/code/client/cl_ui.cpp @@ -264,7 +264,7 @@ void CL_InitUI( void ) { #endif uii.R_ClearScene = re.ClearScene; uii.R_AddRefEntityToScene = re.AddRefEntityToScene; - uii.R_AddPolyToScene = re.AddPolyToScene; + uii.R_AddPolyToScene = re.AddPolyToScene; uii.R_AddLightToScene = re.AddLightToScene; uii.R_RenderScene = re.RenderScene; diff --git a/code/ghoul2/G2.h b/code/ghoul2/G2.h index 38640f62e3..4de04284ea 100644 --- a/code/ghoul2/G2.h +++ b/code/ghoul2/G2.h @@ -215,8 +215,8 @@ void G2_GetBoltMatrixLow(CGhoul2Info &ghoul2,int boltNum,const vec3_t scale,mdx void G2_TimingModel(boneInfo_t &bone,int time,int numFramesInFile,int ¤tFrame,int &newFrame,float &lerp); -bool G2_SetupModelPointers(CGhoul2Info_v &ghoul2); // returns true if any model is properly set up -bool G2_SetupModelPointers(CGhoul2Info *ghlInfo); // returns true if the model is properly set up +qboolean G2_SetupModelPointers(CGhoul2Info_v &ghoul2); // returns true if any model is properly set up +qboolean G2_SetupModelPointers(CGhoul2Info *ghlInfo); // returns true if the model is properly set up //#ifdef _G2_GORE // These exist regardless, non-gore versions are empty void G2API_AddSkinGore(CGhoul2Info_v &ghoul2,SSkinGoreData &gore); diff --git a/code/qcommon/q_shared.cpp b/code/qcommon/q_shared.cpp index 6eb1a67097..a0022f10cd 100644 --- a/code/qcommon/q_shared.cpp +++ b/code/qcommon/q_shared.cpp @@ -157,7 +157,7 @@ void COM_EndParseSession( void ) #endif } -int COM_GetCurrentParseLine( int index ) +int COM_GetCurrentParseLine( void ) { if(parseDataCount < 0) Com_Error(ERR_FATAL, "COM_GetCurrentParseLine: parseDataCount < 0 (be sure to call COM_BeginParseSession!)"); @@ -518,6 +518,33 @@ void SkipBracedSection ( const char **program) { } while (depth && *program); } +/* +================= +SkipBracedSection + +The next token should be an open brace or set depth to 1 if already parsed it. +Skips until a matching close brace is found. +Internal brace depths are properly skipped. +================= +*/ +qboolean SkipBracedSection (const char **program, int depth) { + char *token; + + do { + token = COM_ParseExt( program, qtrue ); + if( token[1] == 0 ) { + if( token[0] == '{' ) { + depth++; + } + else if( token[0] == '}' ) { + depth--; + } + } + } while( depth && *program ); + + return (qboolean)( depth == 0 ); +} + /* ================= SkipRestOfLine diff --git a/code/qcommon/q_shared.h b/code/qcommon/q_shared.h index 732b902593..b8131d4f6f 100644 --- a/code/qcommon/q_shared.h +++ b/code/qcommon/q_shared.h @@ -368,6 +368,7 @@ qboolean COM_ParseVec4( const char **buffer, vec4_t *c); void COM_MatchToken( char**buf_p, char *match ); +qboolean SkipBracedSection (const char **program, int depth); void SkipBracedSection (const char **program); void SkipRestOfLine ( const char **data ); diff --git a/code/qcommon/qfiles.h b/code/qcommon/qfiles.h index 2394d415cf..5d81cf2a14 100644 --- a/code/qcommon/qfiles.h +++ b/code/qcommon/qfiles.h @@ -192,6 +192,131 @@ typedef struct { } md3Header_t; +/* +============================================================================== + +MDR file format + +============================================================================== +*/ + +/* + * Here are the definitions for Ravensoft's model format of md4. Raven stores their + * playermodels in .mdr files, in some games, which are pretty much like the md4 + * format implemented by ID soft. It seems like ID's original md4 stuff is not used at all. + * MDR is being used in EliteForce, JediKnight2 and Soldiers of Fortune2 (I think). + * So this comes in handy for anyone who wants to make it possible to load player + * models from these games. + * This format has bone tags, which is similar to the thing you have in md3 I suppose. + * Raven has released their version of md3view under GPL enabling me to add support + * to this codebase. Thanks to Steven Howes aka Skinner for helping with example + * source code. + * + * - Thilo Schulz (arny@ats.s.bawue.de) + */ + +#define MDR_IDENT (('5'<<24)+('M'<<16)+('D'<<8)+'R') +#define MDR_VERSION 2 +#define MDR_MAX_BONES 128 + +typedef struct { + int boneIndex; // these are indexes into the boneReferences, + float boneWeight; // not the global per-frame bone list + vec3_t offset; +} mdrWeight_t; + +typedef struct { + vec3_t normal; + vec2_t texCoords; + int numWeights; + mdrWeight_t weights[1]; // variable sized +} mdrVertex_t; + +typedef struct { + int indexes[3]; +} mdrTriangle_t; + +typedef struct { + int ident; + + char name[MAX_QPATH]; // polyset name + char shader[MAX_QPATH]; + int shaderIndex; // for in-game use + + int ofsHeader; // this will be a negative number + + int numVerts; + int ofsVerts; + + int numTriangles; + int ofsTriangles; + + // Bone references are a set of ints representing all the bones + // present in any vertex weights for this surface. This is + // needed because a model may have surfaces that need to be + // drawn at different sort times, and we don't want to have + // to re-interpolate all the bones for each surface. + int numBoneReferences; + int ofsBoneReferences; + + int ofsEnd; // next surface follows +} mdrSurface_t; + +typedef struct { + float matrix[3][4]; +} mdrBone_t; + +typedef struct { + vec3_t bounds[2]; // bounds of all surfaces of all LOD's for this frame + vec3_t localOrigin; // midpoint of bounds, used for sphere cull + float radius; // dist from localOrigin to corner + char name[16]; + mdrBone_t bones[1]; // [numBones] +} mdrFrame_t; + +typedef struct { + unsigned char Comp[24]; // MC_COMP_BYTES is in MatComp.h, but don't want to couple +} mdrCompBone_t; + +typedef struct { + vec3_t bounds[2]; // bounds of all surfaces of all LOD's for this frame + vec3_t localOrigin; // midpoint of bounds, used for sphere cull + float radius; // dist from localOrigin to corner + mdrCompBone_t bones[1]; // [numBones] +} mdrCompFrame_t; + +typedef struct { + int numSurfaces; + int ofsSurfaces; // first surface, others follow + int ofsEnd; // next lod follows +} mdrLOD_t; + +typedef struct { + int boneIndex; + char name[32]; +} mdrTag_t; + +typedef struct { + int ident; + int version; + + char name[MAX_QPATH]; // model name + + // frames and bones are shared by all levels of detail + int numFrames; + int numBones; + int ofsFrames; // mdrFrame_t[numFrames] + + // each level of detail has completely separate sets of surfaces + int numLODs; + int ofsLODs; + + int numTags; + int ofsTags; + + int ofsEnd; // end of file +} mdrHeader_t; + /* ============================================================================== @@ -341,8 +466,8 @@ typedef struct { #define MAXLIGHTMAPS 4 #define LS_NORMAL 0x00 #define LS_UNUSED 0xfe -#define LS_NONE 0xff #define MAX_LIGHT_STYLES 64 +#define LS_LSNONE 0xff typedef struct { vec3_t xyz; diff --git a/code/qcommon/tags.h b/code/qcommon/tags.h index 9a6d610a25..fab29257e6 100644 --- a/code/qcommon/tags.h +++ b/code/qcommon/tags.h @@ -67,6 +67,12 @@ along with this program; if not, see . TAGDEF(POINTCACHE), // weather effects TAGDEF(NEWDEL), TAGDEF(MINIZIP), + + TAGDEF(GRIDMESH), // some specific temp workspace that only seems to be in the MP codebase + TAGDEF(GENERAL), + TAGDEF(GHOUL2_GORE), + TAGDEF(TEMP_HUNKALLOC), + TAGDEF(COUNT) //////////////// eof ////////////// diff --git a/code/rd-common/tr_public.h b/code/rd-common/tr_public.h index a0f0ace466..94ffc4ae2a 100644 --- a/code/rd-common/tr_public.h +++ b/code/rd-common/tr_public.h @@ -30,7 +30,7 @@ along with this program; if not, see . #include "../ghoul2/G2.h" #include "../ghoul2/ghoul2_gore.h" -#define REF_API_VERSION 18 +#define REF_API_VERSION 19 typedef struct { void (QDECL *Printf) ( int printLevel, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); @@ -40,7 +40,7 @@ typedef struct { int (*Milliseconds) ( void ); void (*Hunk_ClearToMark) ( void ); - void* (*Malloc) ( int iSize, memtag_t eTag, qboolean zeroIt, int iAlign ); + void* (*Z_Malloc) ( int iSize, memtag_t eTag, qboolean zeroIt, int iAlign ); int (*Z_Free) ( void *memory ); int (*Z_MemSize) ( memtag_t eTag ); void (*Z_MorphMallocTag) ( void *pvBuffer, memtag_t eDesiredTag ); @@ -178,7 +178,7 @@ typedef struct { // Nothing is drawn until R_RenderScene is called. void (*ClearScene)( void ); void (*AddRefEntityToScene)( const refEntity_t *re ); - void (*AddPolyToScene)( qhandle_t hShader , int numVerts, const polyVert_t *verts ); + void (*AddPolyToScene)( qhandle_t hShader , int numVerts, const polyVert_t *verts, int numPolys ); void (*AddLightToScene)( const vec3_t org, float intensity, float r, float g, float b ); void (*RenderScene)( const refdef_t *fd ); qboolean(*GetLighting)( const vec3_t org, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir); @@ -225,7 +225,7 @@ typedef struct { int maxPoints, vec3_t pointBuffer, int maxFragments, markFragment_t *fragmentBuffer ); //model stuff - void (*LerpTag)( orientation_t *tag, qhandle_t model, int startFrame, int endFrame, + int (*LerpTag)( orientation_t *tag, qhandle_t model, int startFrame, int endFrame, float frac, const char *tagName ); void (*ModelBounds)( qhandle_t model, vec3_t mins, vec3_t maxs ); diff --git a/code/rd-common/tr_types.h b/code/rd-common/tr_types.h index a802f6f99d..6e6d63eba9 100644 --- a/code/rd-common/tr_types.h +++ b/code/rd-common/tr_types.h @@ -35,8 +35,10 @@ along with this program; if not, see . #define MAX_REFENTITIES ((1<. #define RF_SHADOW_PLANE 0x00100 // use refEntity->shadowPlane #define RF_WRAP_FRAMES 0x00200 // mod the model frames by the maxframes to allow continuous // animation without needing to know the frame count -#define RF_CAP_FRAMES 0x00400 // cap the model frames by the maxframes for one shot anims -#define RF_ALPHA_FADE 0x00800 // hacks blend mode and uses whatever the set alpha is. -#define RF_PULSATE 0x01000 // for things like a dropped saber, where we want to add an extra visual clue -#define RF_RGB_TINT 0x02000 // overrides ent RGB color to the specified color +#define RF_FORCE_ENT_ALPHA 0x00400 // override shader alpha settings +#define RF_RGB_TINT 0x00800 // override shader rgb settings + +#define RF_SHADOW_ONLY 0x01000 //add surfs for shadowing but don't draw them -rww + +#define RF_DISTORTION 0x02000 //area distortion effect -rww #define RF_FORKED 0x04000 // override lightning to have forks #define RF_TAPERED 0x08000 // lightning tapers #define RF_GROW 0x10000 // lightning grows from start to end during its life -#define RF_SETANIMINDEX 0x20000 //use backEnd.currentEntity->e.skinNum for R_BindAnimatedImage - -#define RF_DISINTEGRATE1 0x40000 // does a procedural hole-ripping thing. -#define RF_DISINTEGRATE2 0x80000 // does a procedural hole-ripping thing with scaling at the ripping point +#define RF_DISINTEGRATE1 0x20000 // does a procedural hole-ripping thing. +#define RF_DISINTEGRATE2 0x40000 // does a procedural hole-ripping thing with scaling at the ripping point -#define RF_G2MINLOD 0x100000 // force Lowest lod on g2 +#define RF_SETANIMINDEX 0x80000 //use backEnd.currentEntity->e.skinNum for R_BindAnimatedImage -#define RF_SHADOW_ONLY 0x200000 //add surfs for shadowing but don't draw them normally -rww +#define RF_ALPHA_DEPTH 0x100000 //depth write on alpha model -#define RF_DISTORTION 0x400000 //area distortion effect -rww +#define RF_FORCEPOST 0x200000 //force it to post-render -rww -#define RF_FORCE_ENT_ALPHA 0x800000 // override shader alpha settings +// SP renderfx flags, only use in SP! +#define RF_CAP_FRAMES 0x400000 // cap the model frames by the maxframes for one shot anims +#define RF_ALPHA_FADE 0x800000 // hacks blend mode and uses whatever the set alpha is. +#define RF_PULSATE 0x1000000 // for things like a dropped saber, where we want to add an extra visual clue +#define RF_G2MINLOD 0x2000000 // force Lowest lod on g2 +#define RF_MORELIGHT 0x4000000 // allways have some light (viewmodel, some items) | SP version which is different from MP // refdef flags #define RDF_NOWORLDMODEL 1 // used for player configuration screen @@ -83,9 +90,12 @@ along with this program; if not, see . #define RDF_SKYBOXPORTAL 8 #define RDF_DRAWSKYBOX 16 // the above marks a scene as being a 'portal sky'. this flag says to draw it or not -#define RDF_doLAGoggles 32 // Light Amp goggles -#define RDF_doFullbright 64 // Light Amp goggles -#define RDF_ForceSightOn 128 // using force sight +#define RDF_AUTOMAP 32 // MP only means this scene is to draw the automap -rww +#define RDF_NOFOG 64 // MP only no global fog in this scene (but still brush fog) -rww +#define RDF_ForceSightOn 128 //using force sight + +#define RDF_doLAGoggles 256 // SP only Light Amp goggles +#define RDF_doFullbright 512 // SP only Light Amp goggles extern int skyboxportal; @@ -105,80 +115,180 @@ typedef struct poly_s { polyVert_t *verts; } poly_t; -typedef enum -{ +typedef enum { RT_MODEL, RT_POLY, RT_SPRITE, RT_ORIENTED_QUAD, - RT_LINE, - RT_ELECTRICITY, - RT_CYLINDER, - RT_LATHE, RT_BEAM, RT_SABER_GLOW, + RT_ELECTRICITY, RT_PORTALSURFACE, // doesn't draw anything, just info for portals + RT_LINE, + RT_ORIENTEDLINE, + RT_CYLINDER, + RT_ENT_CHAIN, + + RT_MAX_MP_REF_ENTITY_TYPE, + // SP ONLY Entity Types! + RT_LATHE, RT_CLOUDS, - RT_MAX_REF_ENTITY_TYPE + RT_MAX_SP_REF_ENTITY_TYPE } refEntityType_t; -typedef struct { - refEntityType_t reType; - int renderfx; +typedef struct miniRefEntity_s +{ + refEntityType_t reType; + int renderfx; - qhandle_t hModel; // opaque type outside refresh + qhandle_t hModel; // opaque type outside refresh // most recent data - vec3_t lightingOrigin; // so multi-part models can be lit identically (RF_LIGHTING_ORIGIN) - float shadowPlane; // projection shadows go here, stencils go slightly lower + matrix3_t axis; // rotation vectors + qboolean nonNormalizedAxes; // axis are not normalized, i.e. they have scale + vec3_t origin; // also used as MODEL_BEAM's "from" + + // previous data for frame interpolation + vec3_t oldorigin; // also used as MODEL_BEAM's "to" + + // texturing + qhandle_t customShader; // use one image for the entire thing - vec3_t axis[3]; // rotation vectors - qboolean nonNormalizedAxes; // axis are not normalized, i.e. they have scale - float origin[3]; // also used as MODEL_BEAM's "from" + // misc + byte shaderRGBA[4]; // colors used by rgbgen entity shaders + vec2_t shaderTexCoord; // texture coordinates used by tcMod entity modifiers + + // extra sprite information + float radius; + float rotation; // size 2 for RT_CYLINDER or number of verts in RT_ELECTRICITY + + // misc + float shaderTime; // subtracted from refdef time to control effect start times int frame; // also used as MODEL_BEAM's diameter +} miniRefEntity_t; + +typedef struct refEntity_s { + // this stucture must remain identical as the miniRefEntity_t + // + // + refEntityType_t reType; + int renderfx; + + qhandle_t hModel; // opaque type outside refresh + + // most recent data + matrix3_t axis; // rotation vectors + qboolean nonNormalizedAxes; // axis are not normalized, i.e. they have scale + vec3_t origin; // also used as MODEL_BEAM's "from" + // previous data for frame interpolation - float oldorigin[3]; // also used as MODEL_BEAM's "to" - int oldframe; - float backlerp; // 0.0 = current, 1.0 = old + vec3_t oldorigin; // also used as MODEL_BEAM's "to" // texturing - int skinNum; // inline skin index + qhandle_t customShader; // use one image for the entire thing - qhandle_t customSkin; // NULL for default skin - qhandle_t customShader; // use one image for the entire thing + // misc + byte shaderRGBA[4]; // colors used by rgbgen entity shaders + vec2_t shaderTexCoord; // texture coordinates used by tcMod entity modifiers + + // extra sprite information + float radius; + float rotation; // misc - byte shaderRGBA[4]; // colors used by colorSrc=vertex shaders - float shaderTexCoord[2]; // texture coordinates used by tcMod=vertex modifiers float shaderTime; // subtracted from refdef time to control effect start times + int frame; // also used as MODEL_BEAM's diameter + // + // + // end miniRefEntity_t - // extra sprite information - float radius; + // + // + // specific full refEntity_t data + // + // + + // most recent data + vec3_t lightingOrigin; // so multi-part models can be lit identically (RF_LIGHTING_ORIGIN) + float shadowPlane; // projection shadows go here, stencils go slightly lower - // This doesn't have to be unioned, but it does make for more meaningful variable names :) + // previous data for frame interpolation + int oldframe; + float backlerp; // 0.0 = current, 1.0 = old + + // texturing + int skinNum; // inline skin index + qhandle_t customSkin; // NULL for default skin + + // texturing union { - float rotation; - float endTime; - float saberLength; - }; + // int skinNum; // inline skin index + // ivec3_t terxelCoords; // coords of patch for RT_TERXELS + struct + { + int miniStart; + int miniCount; + } uMini; + } uRefEnt; -/* -Ghoul2 Insert Start -*/ + // extra sprite information + union { + struct + { + float rotation; + float radius; + byte vertRGBA[4][4]; + } sprite; + struct + { + float width; + float width2; + float stscale; + } line; + struct // that whole put-the-opening-brace-on-the-same-line-as-the-beginning-of-the-definition coding style is fecal + { + float width; + vec3_t control1; + vec3_t control2; + } bezier; + struct + { + float width; + float width2; + float stscale; + float height; + float bias; + qboolean wrap; + } cylinder; + struct + { + float width; + float deviation; + float stscale; + qboolean wrap; + qboolean taper; + } electricity; + } data; + + float endTime; + float saberLength; + + /* + Ghoul2 Insert Start + */ vec3_t angles; // rotation angles - used for Ghoul2 vec3_t modelScale; // axis scale for models - CGhoul2Info_v *ghoul2; // has to be at the end of the ref-ent in order for it to be created properly +// CGhoul2Info_v *ghoul2; // has to be at the end of the ref-ent in order for it to be created properly + void *ghoul2; // has to be at the end of the ref-ent in order for it to be created properly /* Ghoul2 Insert End */ - } refEntity_t; - #define MAX_RENDER_STRINGS 8 #define MAX_RENDER_STRING_LENGTH 32 @@ -186,7 +296,8 @@ typedef struct { int x, y, width, height; float fov_x, fov_y; vec3_t vieworg; - vec3_t viewaxis[3]; // transformation matrix + vec3_t viewangles; + matrix3_t viewaxis; // transformation matrix int viewContents; // world contents at vieworg // time in milliseconds for shader effects and other time dependent rendering issues @@ -198,7 +309,7 @@ typedef struct { byte areamask[MAX_MAP_AREA_BYTES]; // text messages for deform text shaders -// char text[MAX_RENDER_STRINGS][MAX_RENDER_STRING_LENGTH]; + char text[MAX_RENDER_STRINGS][MAX_RENDER_STRING_LENGTH]; } refdef_t; @@ -219,7 +330,8 @@ typedef enum { typedef enum { TC_NONE, TC_S3TC, - TC_S3TC_DXT + TC_S3TC_DXT, + TC_S3TC_ARB } textureCompression_t; typedef struct glconfig_s { @@ -227,6 +339,7 @@ typedef struct glconfig_s { const char *vendor_string; const char *version_string; const char *extensions_string; + int maxTextureSize; // queried from GL int maxActiveTextures; // multitexture ability float maxTextureFilterAnisotropy; @@ -236,15 +349,12 @@ typedef struct glconfig_s { qboolean deviceSupportsGamma; textureCompression_t textureCompression; qboolean textureEnvAddAvailable; - qboolean textureFilterAnisotropicAvailable; qboolean clampToEdgeAvailable; int vidWidth, vidHeight; int displayFrequency; - qboolean doStencilShadowsInOneDrawcall; - // synonymous with "does rendering consume the entire screen?", therefore // a Voodoo or Voodoo2 will have this set to TRUE, as will a Win32 ICD that // used CDS. diff --git a/code/rd-rend2/CMakeLists.txt b/code/rd-rend2/CMakeLists.txt new file mode 100644 index 0000000000..09a12e2636 --- /dev/null +++ b/code/rd-rend2/CMakeLists.txt @@ -0,0 +1,235 @@ +# Make sure the user is not executing this script directly +if(NOT InOpenJK) + message(FATAL_ERROR "Use the top-level cmake script!") +endif(NOT InOpenJK) + +set(SPRend2IncludeDirectories + "${SharedDir}" + "${SharedDir}/rd-rend2" + "${SPDir}" + "${SPDir}/rd-rend2" + "${GSLIncludeDirectory}" + ) + +set(SPRend2Files + "${SharedDir}/rd-rend2/iqm.h" + "${SharedDir}/rd-rend2/glext.h" + "${SharedDir}/rd-rend2/qgl.h" + "${SharedDir}/rd-rend2/stb_image.h" + "${SPDir}/rd-rend2/G2_API.cpp" + "${SPDir}/rd-rend2/G2_bolts.cpp" + "${SPDir}/rd-rend2/G2_bones.cpp" + "${SharedDir}/rd-rend2/G2_gore_r2.cpp" + "${SharedDir}/rd-rend2/G2_gore_r2.h" + "${SPDir}/rd-rend2/G2_misc.cpp" + "${SPDir}/rd-rend2/G2_surfaces.cpp" + "${SharedDir}/rd-rend2/tr_allocator.cpp" + "${SharedDir}/rd-rend2/tr_allocator.h" + "${SharedDir}/rd-rend2/tr_animation.cpp" + "${SharedDir}/rd-rend2/tr_backend.cpp" + "${SharedDir}/rd-rend2/tr_bsp.cpp" + "${SharedDir}/rd-rend2/tr_cache.cpp" + "${SharedDir}/rd-rend2/tr_cache.h" + "${SharedDir}/rd-rend2/tr_cmds.cpp" + "${SharedDir}/rd-rend2/tr_curve.cpp" + "${SharedDir}/rd-rend2/tr_decals.cpp" + "${SPDir}/rd-rend2/tr_draw.cpp" + "${SharedDir}/rd-rend2/tr_extensions.cpp" + "${SharedDir}/rd-rend2/tr_extramath.cpp" + "${SharedDir}/rd-rend2/tr_extramath.h" + "${SharedDir}/rd-rend2/tr_extratypes.h" + "${SharedDir}/rd-rend2/tr_fbo.cpp" + "${SharedDir}/rd-rend2/tr_fbo.h" + "${SharedDir}/rd-rend2/tr_flares.cpp" + "${SharedDir}/rd-rend2/tr_ghoul2.cpp" + "${SharedDir}/rd-rend2/tr_glsl.cpp" + "${SharedDir}/rd-rend2/tr_glsl_parse.cpp" + "${SharedDir}/rd-rend2/tr_image.cpp" + "${SharedDir}/rd-rend2/tr_image_stb.cpp" + "${SPDir}/rd-rend2/tr_init.cpp" + "${SharedDir}/rd-rend2/tr_light.cpp" + "${SharedDir}/rd-rend2/tr_local.h" + "${SharedDir}/rd-rend2/tr_main.cpp" + "${SharedDir}/rd-rend2/tr_marks.cpp" + "${SharedDir}/rd-rend2/tr_mesh.cpp" + "${SharedDir}/rd-rend2/tr_model.cpp" + "${SharedDir}/rd-rend2/tr_model_iqm.cpp" + "${SharedDir}/rd-rend2/tr_postprocess.cpp" + "${SharedDir}/rd-rend2/tr_postprocess.h" + "${SharedDir}/rd-rend2/tr_scene.cpp" + "${SharedDir}/rd-rend2/tr_shade.cpp" + "${SharedDir}/rd-rend2/tr_shade_calc.cpp" + "${SharedDir}/rd-rend2/tr_shader.cpp" + "${SharedDir}/rd-rend2/tr_shadows.cpp" + "${SharedDir}/rd-rend2/tr_skin.cpp" + "${SharedDir}/rd-rend2/tr_sky.cpp" + "${SharedDir}/rd-rend2/tr_subs.cpp" + "${SharedDir}/rd-rend2/tr_surface.cpp" + "${SharedDir}/rd-rend2/tr_tangentspace.cpp" + "${SharedDir}/rd-rend2/tr_vbo.cpp" + "${SharedDir}/rd-rend2/tr_world.cpp" + "${SharedDir}/rd-rend2/tr_weather.cpp" + "${SharedDir}/rd-rend2/tr_weather.h") +source_group("renderer" FILES ${SPRend2Files}) + +file(GLOB SPRend2GLSLFiles "${SharedDir}/rd-rend2/glsl/*.glsl") +source_group("renderer\\glsl" FILES ${SPRend2GLSLFiles}) +set(SPRend2Files ${SPRend2Files} ${SPRend2GLSLFiles}) + +set(SPRend2MikktFiles + "${SharedDir}/rd-rend2/MikkTSpace/mikktspace.h" + "${SharedDir}/rd-rend2/MikkTSpace/mikktspace.c") +source_group("MikktSpace" FILES ${SPRend2MikktFiles}) +set(SPRend2Files ${SPRend2Files} ${SPRend2MikktFiles}) + +set(SPRend2Ghoul2Files + "${SPDir}/ghoul2/G2.h" + "${SPDir}/ghoul2/ghoul2_gore.h") +source_group("ghoul2" FILES ${SPRend2Ghoul2Files}) +set(SPRend2Files ${SPRend2Files} ${SPRend2Ghoul2Files}) + +set(SPRend2RdCommonFiles + "${SPDir}/rd-common/mdx_format.h" + "${SPDir}/rd-common/tr_common.h" + "${SPDir}/rd-common/tr_font.cpp" + "${SPDir}/rd-common/tr_font.h" + "${SPDir}/rd-common/tr_image_load.cpp" + "${SPDir}/rd-common/tr_image_jpg.cpp" + "${SPDir}/rd-common/tr_image_tga.cpp" + "${SPDir}/rd-common/tr_image_png.cpp" + "${SPDir}/rd-common/tr_noise.cpp" + "${SPDir}/rd-common/tr_public.h" + "${SPDir}/rd-common/tr_types.h") +source_group("rd-common" FILES ${SPRend2RdCommonFiles}) +set(SPRend2Files ${SPRend2Files} ${SPRend2RdCommonFiles}) + +set(SPRend2CommonFiles + "${SPDir}/qcommon/matcomp.cpp" + "${SPDir}/qcommon/q_shared.cpp" + "${SharedCommonFiles}") +source_group("common" FILES ${SPRend2CommonFiles}) +set(SPRend2Files ${SPRend2Files} ${SPRend2CommonFiles}) + +set(SPRend2CommonSafeFiles + ${SharedCommonSafeFiles} + ) +source_group("common/safe" FILES ${SPRend2CommonSafeFiles}) +set(SPRend2Files ${SPRend2Files} ${SPRend2CommonSafeFiles}) + +# Transparently use either bundled or system libjpeg. +list(APPEND SPRend2IncludeDirectories ${JPEG_INCLUDE_DIR}) +list(APPEND SPRend2Libraries ${JPEG_LIBRARIES}) + +# Transparently use either bundled or system libpng. Order is important -- +# libpng used zlib, so it must come before it on the linker command line. +list(APPEND SPRend2IncludeDirectories ${PNG_INCLUDE_DIRS}) +list(APPEND SPRend2Libraries ${PNG_LIBRARIES}) + +# Transparently use either bundled or system zlib. +list(APPEND SPRend2IncludeDirectories ${ZLIB_INCLUDE_DIR}) +list(APPEND SPRend2Libraries ${ZLIB_LIBRARIES}) + +# Transparently use our bundled minizip. +list(APPEND SPRend2IncludeDirectories ${MINIZIP_INCLUDE_DIRS}) +list(APPEND SPRend2Libraries ${MINIZIP_LIBRARIES}) + +find_package(OpenGL REQUIRED) +set(SPRend2IncludeDirectories ${SPRend2IncludeDirectories} ${OPENGL_INCLUDE_DIR}) +set(SPRend2Libraries ${SPRend2Libraries} ${OPENGL_LIBRARIES}) + +source_group("renderer" + FILES + ${CMAKE_CURRENT_BINARY_DIR}/glsl_shaders.h + ${CMAKE_CURRENT_BINARY_DIR}/glsl_shaders.cpp) +set(SPRend2Files + ${SPRend2Files} + ${CMAKE_CURRENT_BINARY_DIR}/glsl_shaders.h + ${CMAKE_CURRENT_BINARY_DIR}/glsl_shaders.cpp) + +set(SPRend2IncludeDirectories ${SPRend2IncludeDirectories} ${OpenJKLibDir}) + +function(add_sp_renderer_project ProjectName Label EngineName InstallDir Component) + add_library(${ProjectName} SHARED ${SPRend2Files}) + if(NOT MSVC) + # remove "lib" prefix for .so/.dylib files + set_target_properties(${ProjectName} PROPERTIES PREFIX "") + endif() + + if(WIN32) + install(TARGETS ${ProjectName} + RUNTIME + DESTINATION ${InstallDir} + COMPONENT ${Component}) + else(WIN32) + if(MakeApplicationBundles AND (BuildSPEngine OR BuildJK2SPEngine)) + install(TARGETS ${ProjectName} + LIBRARY + DESTINATION "${InstallDir}/${EngineName}.app/Contents/MacOS/" + COMPONENT ${Component}) + else() + install(TARGETS ${ProjectName} + LIBRARY + DESTINATION ${InstallDir} + COMPONENT ${Component}) + endif() + endif() + + set_target_properties(${ProjectName} PROPERTIES COMPILE_DEFINITIONS "${SPRend2Defines}") + + # Hide symbols not explicitly marked public. + set_property(TARGET ${ProjectName} APPEND PROPERTY COMPILE_OPTIONS ${OPENJK_VISIBILITY_FLAGS}) + + set_target_properties(${ProjectName} PROPERTIES INCLUDE_DIRECTORIES "${SPRend2IncludeDirectories}") + set_target_properties(${ProjectName} PROPERTIES PROJECT_LABEL ${Label}) + + target_link_libraries(${ProjectName} ${SPRend2Libraries}) + target_include_directories(${ProjectName} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) +endfunction(add_sp_renderer_project) + +# Defines +set(SPRend2Defines ${SharedDefines} "RENDERER" "REND2_SP" "REND2_SP_GORE") + +if(BuildSPRend2) + add_sp_renderer_project(${SPRend2} "SP Rend2 Renderer" ${SPEngine} ${JKAInstallDir} ${JKASPClientComponent}) +endif(BuildSPRend2) +if(BuildJK2SPRdRend2) + set(SPRend2Defines ${SPRend2Defines} "JK2_MODE") + add_sp_renderer_project(${JK2SPRend2Renderer} "JK2 SP Rend2 Renderer" ${JK2SPEngine} ${JK2InstallDir} ${JK2SPClientComponent}) +endif(BuildJK2SPRdRend2) + +# GLSL shader file generator +add_executable(compact_glsl_sp + ${SharedDir}/rd-rend2/glsl/compact.cpp + ${SharedDir}/rd-rend2/tr_allocator.cpp + ${SharedDir}/rd-rend2/tr_allocator.h + ${SharedDir}/rd-rend2/tr_glsl_parse.cpp) +target_compile_definitions(compact_glsl_sp PRIVATE "GLSL_BUILDTOOL" "NOMINMAX" "REND2_SP") +if (NOT WIN32 AND NOT APPLE) + target_compile_definitions(compact_glsl_sp PRIVATE "ARCH_STRING=\"${Architecture}\"") +endif() +target_include_directories(compact_glsl_sp PRIVATE "${SPRend2IncludeDirectories}") +if (WIN32 OR APPLE) +add_custom_command( + OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/glsl_shaders.cpp + ${CMAKE_CURRENT_BINARY_DIR}/glsl_shaders.h + COMMAND + compact_glsl_sp + ${CMAKE_CURRENT_BINARY_DIR}/glsl_shaders.cpp + ${CMAKE_CURRENT_BINARY_DIR}/glsl_shaders.h + ${SPRend2GLSLFiles} + DEPENDS + compact_glsl_sp ${SPRend2GLSLFiles}) +else() +add_custom_command( + OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/glsl_shaders.cpp + ${CMAKE_CURRENT_BINARY_DIR}/glsl_shaders.h + COMMAND + ${CMAKE_BINARY_DIR}/compact_glsl_sp + ${CMAKE_CURRENT_BINARY_DIR}/glsl_shaders.cpp + ${CMAKE_CURRENT_BINARY_DIR}/glsl_shaders.h + ${SPRend2GLSLFiles} + DEPENDS + compact_glsl_sp ${SPRend2GLSLFiles}) +endif() diff --git a/code/rd-rend2/G2_API.cpp b/code/rd-rend2/G2_API.cpp new file mode 100644 index 0000000000..5a290a7423 --- /dev/null +++ b/code/rd-rend2/G2_API.cpp @@ -0,0 +1,2536 @@ +#include "server/exe_headers.h" + +#include "ghoul2/G2.h" +#include "ghoul2/ghoul2_gore.h" // ragdoll +#include "qcommon/q_shared.h" +#include "qcommon/MiniHeap.h" +#include "rd-common/tr_common.h" +#include "tr_local.h" +#include + +#ifdef _MSC_VER + #pragma warning (push, 3) //go back down to 3 for the stl include +#endif +#include +#ifdef _MSC_VER + #pragma warning (pop) +#endif + +extern mdxaBone_t worldMatrix; +extern mdxaBone_t worldMatrixInv; + +#define NUM_G2T_TIME (2) +#ifndef REND2_SP +// must be a power of two +#define MAX_G2_MODELS (1024) +#define G2_MODEL_BITS (10) +#else +#define MAX_G2_MODELS (512) +#define G2_MODEL_BITS (9) +#endif +#define G2_INDEX_MASK (MAX_G2_MODELS-1) +// rww - RAGDOLL_BEGIN +#define GHOUL2_RAG_STARTED 0x0010 +#define GHOUL2_RAG_FORCESOLVE 0x1000 //api-override, determine if ragdoll should be forced to continue solving even if it thinks it is settled +// rww - RAGDOLL_END + +#if G2API_DEBUG + +#define G2ERROR(exp,m) (void)( (exp) || (G2APIError().Error(m,0,__FILE__,__LINE__), 0) ) +#define G2WARNING(exp,m) (void)( (exp) || (G2APIError().Error(m,1,__FILE__,__LINE__), 0) ) +#define G2NOTE(exp,m) (void)( (exp) || (G2APIError().Error(m,2,__FILE__,__LINE__), 0) ) +#define G2ANIM(ghlInfo,m) (void)((G2APIError().AnimTest(ghlInfo,m,__FILE__,__LINE__), 0) ) + +#else + +#define G2ERROR(exp,m) ((void)0) +#define G2WARNING(exp,m) ((void)0) +#define G2NOTE(exp,m) ((void)0) +#define G2ANIM(ghlInfo,m) ((void)0) + +#endif + +// get/set time +static int G2TimeBases[NUM_G2T_TIME]; + +// used in tr_init.cpp +qboolean gG2_GBMNoReconstruct; +qboolean gG2_GBMUseSPMethod; + +// Local functions pre-definition +qboolean G2_TestModelPointers(CGhoul2Info* ghlInfo); +void CL_InitRef(void); + +#ifdef _FULL_G2_LEAK_CHECKING +int g_Ghoul2Allocations = 0; +int g_G2ServerAlloc = 0; +int g_G2ClientAlloc = 0; +int g_G2AllocServer = 0; + +//stupid debug crap to track leaks in case they happen. +//we used to shove everything into a map and delete it all and not care about +//leaks, but that was not the Right Thing. -rww +#define MAX_TRACKED_ALLOC 4096 +static bool g_G2AllocTrackInit = false; //want to keep this thing contained +static CGhoul2Info_v *g_G2AllocTrack[MAX_TRACKED_ALLOC]; + +void G2_DEBUG_InitPtrTracker(void) +{ + memset(g_G2AllocTrack, 0, sizeof(g_G2AllocTrack)); + g_G2AllocTrackInit = true; +} + +void G2_DEBUG_ReportLeaks(void) +{ + int i = 0; + + if (!g_G2AllocTrackInit) + { + Com_Printf("g2 leak tracker was never initialized!\n"); + return; + } + + while (i < MAX_TRACKED_ALLOC) + { + if (g_G2AllocTrack[i]) + { + Com_Printf("Bad guy found in slot %i, attempting to access...", i); + CGhoul2Info_v &g2v = *g_G2AllocTrack[i]; + CGhoul2Info &g2 = g2v[0]; + + if (g2v.IsValid() && g2.mFileName && g2.mFileName[0]) + { + Com_Printf("Bad guy's filename is %s\n", g2.mFileName); + } + else + { + Com_Printf("He's not valid! BURN HIM!\n"); + } + } + i++; + } +} + +void G2_DEBUG_ShovePtrInTracker(CGhoul2Info_v *g2) +{ + int i = 0; + + if (!g_G2AllocTrackInit) + { + G2_DEBUG_InitPtrTracker(); + } + + if (!g_G2AllocTrackInit) + { + G2_DEBUG_InitPtrTracker(); + } + + while (i < MAX_TRACKED_ALLOC) + { + if (!g_G2AllocTrack[i]) + { + g_G2AllocTrack[i] = g2; + return; + } + i++; + } + + CGhoul2Info_v &g2v = *g2; + + if (g2v[0].currentModel && g2v[0].currentModel->name && g2v[0].currentModel->name[0]) + { + Com_Printf("%s could not be fit into g2 debug instance tracker.\n", g2v[0].currentModel->name); + } + else + { + Com_Printf("Crap g2 instance passed to instance tracker (in).\n"); + } +} + +void G2_DEBUG_RemovePtrFromTracker(CGhoul2Info_v *g2) +{ + int i = 0; + + if (!g_G2AllocTrackInit) + { + G2_DEBUG_InitPtrTracker(); + } + + while (i < MAX_TRACKED_ALLOC) + { + if (g_G2AllocTrack[i] == g2) + { + g_G2AllocTrack[i] = NULL; + return; + } + i++; + } + + CGhoul2Info_v &g2v = *g2; + + if (g2v[0].currentModel && g2v[0].currentModel->name && g2v[0].currentModel->name[0]) + { + Com_Printf("%s not in g2 debug instance tracker.\n", g2v[0].currentModel->name); + } + else + { + Com_Printf("Crap g2 instance passed to instance tracker (out).\n"); + } +} +#endif + +// RAGDOLL_BEGIN +void G2API_SetTime(int currentTime,int clock) +{ + assert(clock>=0&&clockG2TimeBases[0]+200) + { + G2TimeBases[1]=0; // use server time instead + return; + } +#if G2_DEBUG_TIME + Com_Printf(" after c%6d s%6d\n",G2TimeBases[1],G2TimeBases[0]); +#endif +} + +int G2API_GetTime(int argTime) // this may or may not return arg depending on ghoul2_time cvar +{ + int ret=G2TimeBases[1]; + if ( !ret ) + { + ret = G2TimeBases[0]; + } + + return ret; +} +//rww - RAGDOLL_END + +void G2API_AttachInstanceToEntNum(CGhoul2Info_v &ghoul2, int entityNum, qboolean server) +{ //Assign the pointers in the arrays +#ifdef _G2_LISTEN_SERVER_OPT + if (server) + { + ghoul2[0].entityNum = entityNum; + } + else + { + g2ClientAttachments[entityNum] = &ghoul2; + } +#endif +} + +void G2API_ClearAttachedInstance(int entityNum) +{ +#ifdef _G2_LISTEN_SERVER_OPT + g2ClientAttachments[entityNum] = NULL; +#endif +} + +void G2API_CleanEntAttachments(void) +{ +#ifdef _G2_LISTEN_SERVER_OPT + int i = 0; + + while (i < MAX_GENTITIES) + { + g2ClientAttachments[i] = NULL; + i++; + } +#endif +} + +#ifdef _G2_LISTEN_SERVER_OPT +void CopyBoneCache(CBoneCache *to, CBoneCache *from); +#endif + +qboolean G2API_OverrideServerWithClientData(CGhoul2Info_v& ghoul2, int modelIndex) +{ +#ifndef _G2_LISTEN_SERVER_OPT + return qfalse; +#else + CGhoul2Info *serverInstance = &ghoul2[modelIndex]; + CGhoul2Info *clientInstance; + + if (ri.Cvar_VariableIntegerValue( "dedicated" )) + { //No client to get from! + return qfalse; + } + + if (!g2ClientAttachments[serverInstance->entityNum]) + { //No clientside instance is attached to this entity + return qfalse; + } + + CGhoul2Info_v &g2Ref = *g2ClientAttachments[serverInstance->entityNum]; + clientInstance = &g2Ref[0]; + + int frameNum = G2API_GetTime(0); + + if (clientInstance->mSkelFrameNum != frameNum) + { //it has to be constructed already + return qfalse; + } + + if (!clientInstance->mBoneCache) + { //that just won't do + return qfalse; + } + + //Just copy over the essentials + serverInstance->aHeader = clientInstance->aHeader; + serverInstance->animModel = clientInstance->animModel; + serverInstance->currentAnimModelSize = clientInstance->currentAnimModelSize; + serverInstance->currentModel = clientInstance->currentModel; + serverInstance->currentModelSize = clientInstance->currentModelSize; + serverInstance->mAnimFrameDefault = clientInstance->mAnimFrameDefault; + serverInstance->mModel = clientInstance->mModel; + serverInstance->mModelindex = clientInstance->mModelindex; + serverInstance->mSurfaceRoot = clientInstance->mSurfaceRoot; + serverInstance->mTransformedVertsArray = clientInstance->mTransformedVertsArray; + + if (!serverInstance->mBoneCache) + { //if this is the case.. I guess we can use the client one instead + serverInstance->mBoneCache = clientInstance->mBoneCache; + } + + //Copy the contents of the client cache over the contents of the server cache + if (serverInstance->mBoneCache != clientInstance->mBoneCache) + { + CopyBoneCache(serverInstance->mBoneCache, clientInstance->mBoneCache); + } + + serverInstance->mSkelFrameNum = clientInstance->mSkelFrameNum; + return qtrue; +#endif +} + +void RemoveBoneCache(CBoneCache* boneCache); + +static size_t GetSizeOfGhoul2Info ( const CGhoul2Info& g2Info ) +{ + size_t size = 0; + + // This is pretty ugly, but we don't want to save everything in the CGhoul2Info object. + size += offsetof (CGhoul2Info, mTransformedVertsArray) - offsetof (CGhoul2Info, mModelindex); + + // Surface vector + size + size += sizeof (int); + size += g2Info.mSlist.size() * sizeof (surfaceInfo_t); + + // Bone vector + size + size += sizeof (int); + size += g2Info.mBlist.size() * sizeof (boneInfo_t); + + // Bolt vector + size + size += sizeof (int); + size += g2Info.mBltlist.size() * sizeof (boltInfo_t); + + return size; +} + +static size_t SerializeGhoul2Info ( char *buffer, const CGhoul2Info& g2Info ) +{ + char *base = buffer; + size_t blockSize; + + // Oh the ugliness... + blockSize = offsetof (CGhoul2Info, mTransformedVertsArray) - offsetof (CGhoul2Info, mModelindex); + memcpy (buffer, &g2Info.mModelindex, blockSize); + buffer += blockSize; + + // Surfaces vector + size + *(int *)buffer = g2Info.mSlist.size(); + buffer += sizeof (int); + + blockSize = g2Info.mSlist.size() * sizeof (surfaceInfo_t); + memcpy (buffer, g2Info.mSlist.data(), g2Info.mSlist.size() * sizeof (surfaceInfo_t)); + buffer += blockSize; + + // Bones vector + size + *(int *)buffer = g2Info.mBlist.size(); + buffer += sizeof (int); + + blockSize = g2Info.mBlist.size() * sizeof (boneInfo_t); + memcpy (buffer, g2Info.mBlist.data(), g2Info.mBlist.size() * sizeof (boneInfo_t)); + buffer += blockSize; + + // Bolts vector + size + *(int *)buffer = g2Info.mBltlist.size(); + buffer += sizeof (int); + + blockSize = g2Info.mBltlist.size() * sizeof (boltInfo_t); + memcpy (buffer, g2Info.mBltlist.data(), g2Info.mBltlist.size() * sizeof (boltInfo_t)); + buffer += blockSize; + + return static_cast(buffer - base); +} + +static size_t DeserializeGhoul2Info ( const char *buffer, CGhoul2Info& g2Info ) +{ + const char *base = buffer; + size_t size; + + size = offsetof (CGhoul2Info, mTransformedVertsArray) - offsetof (CGhoul2Info, mModelindex); + memcpy (&g2Info.mModelindex, buffer, size); + buffer += size; + + // Surfaces vector + size = *(int *)buffer; + buffer += sizeof (int); + + g2Info.mSlist.assign ((surfaceInfo_t *)buffer, (surfaceInfo_t *)buffer + size); + buffer += sizeof (surfaceInfo_t) * size; + + // Bones vector + size = *(int *)buffer; + buffer += sizeof (int); + + g2Info.mBlist.assign ((boneInfo_t *)buffer, (boneInfo_t *)buffer + size); + buffer += sizeof (boneInfo_t) * size; + + // Bolt vector + size = *(int *)buffer; + buffer += sizeof (int); + + g2Info.mBltlist.assign ((boltInfo_t *)buffer, (boltInfo_t *)buffer + size); + buffer += sizeof (boltInfo_t) * size; + + return static_cast(buffer - base); +} + +class Ghoul2InfoArray : public IGhoul2InfoArray +{ + std::vector mInfos[MAX_G2_MODELS]; + int mIds[MAX_G2_MODELS]; + std::list mFreeIndecies; + void DeleteLow(int idx) + { + for (size_t model=0; model< mInfos[idx].size(); model++) + { + if (mInfos[idx][model].mBoneCache) + { + RemoveBoneCache(mInfos[idx][model].mBoneCache); + mInfos[idx][model].mBoneCache=0; + } + } + + mInfos[idx].clear(); + + if ((mIds[idx]>>G2_MODEL_BITS)>(1<<(31-G2_MODEL_BITS))) + { + mIds[idx]=MAX_G2_MODELS+idx; //rollover reset id to minimum value + mFreeIndecies.push_back(idx); + } + else + { + mIds[idx]+=MAX_G2_MODELS; + mFreeIndecies.push_front(idx); + } + } +public: + Ghoul2InfoArray() + { + int i; + for (i=0;i(buffer - base); + } + + size_t Deserialize ( const char *buffer, size_t size ) + { + const char *base = buffer; + size_t count; + + // Free indices + count = *(int *)buffer; + buffer += sizeof (int); + + mFreeIndecies.assign ((int *)buffer, (int *)buffer + count); + buffer += sizeof (int) * count; + + // IDs + memcpy (mIds, buffer, sizeof (mIds)); + buffer += sizeof (mIds); + + // Ghoul2 infos + for ( size_t i = 0; i < MAX_G2_MODELS; i++ ) + { + mInfos[i].clear(); + + count = *(int *)buffer; + buffer += sizeof (int); + + mInfos[i].resize (count); + + for ( size_t j = 0; j < count; j++ ) + { + buffer += DeserializeGhoul2Info (buffer, mInfos[i][j]); + } + } + + return static_cast(buffer - base); + } + + ~Ghoul2InfoArray() + { + if (mFreeIndecies.size() < MAX_G2_MODELS) + { +#if G2API_DEBUG + char mess[1000]; + sprintf(mess, "************************\nLeaked %ld ghoul2info slots\n", MAX_G2_MODELS - mFreeIndecies.size()); + Com_DPrintf(mess); +#endif + for (int i = 0; i < MAX_G2_MODELS; i++) + { + std::list::iterator j; + for (j = mFreeIndecies.begin(); j != mFreeIndecies.end(); ++j) + { + if (*j == i) + break; + } + if (j == mFreeIndecies.end()) + { +#if G2API_DEBUG + sprintf(mess, "Leaked Info idx=%d id=%d sz=%ld\n", i, mIds[i], mInfos[i].size()); + Com_DPrintf(mess); + if (mInfos[i].size()) + { + sprintf(mess, "%s\n", mInfos[i][0].mFileName); + Com_DPrintf(mess); + } +#endif + DeleteLow(i); + } + } + } +#if G2API_DEBUG + else + { + Com_DPrintf("No ghoul2 info slots leaked\n"); + } +#endif + } + + int New() + { + if (mFreeIndecies.empty()) + { + assert(0); + Com_Error(ERR_FATAL, "Out of ghoul2 info slots"); + + } + // gonna pull from the front, doing a + int idx=*mFreeIndecies.begin(); + mFreeIndecies.erase(mFreeIndecies.begin()); + return mIds[idx]; + } + bool IsValid(int handle) const + { + if ( handle <= 0 ) + { + return false; + } + assert((handle&G2_INDEX_MASK)>=0&&(handle&G2_INDEX_MASK) 0); //null handle + assert((handle & G2_INDEX_MASK) >= 0 && (handle & G2_INDEX_MASK) < MAX_G2_MODELS); //junk handle + assert(mIds[handle & G2_INDEX_MASK] == handle); // not a valid handle, could be old or garbage + if (mIds[handle & G2_INDEX_MASK] == handle) + { + DeleteLow(handle&G2_INDEX_MASK); + } + } + std::vector &Get(int handle) + { + assert(handle>0); //null handle + assert((handle&G2_INDEX_MASK)>=0&&(handle&G2_INDEX_MASK)=MAX_G2_MODELS||mIds[handle&G2_INDEX_MASK]!=handle)); + + return mInfos[handle&G2_INDEX_MASK]; + } + const std::vector &Get(int handle) const + { + assert(handle>0); + assert(mIds[handle&G2_INDEX_MASK]==handle); // not a valid handle, could be old or garbage + return mInfos[handle&G2_INDEX_MASK]; + } + +#if G2API_DEBUG + std::vector& GetDebug(int handle) + { + assert(!(handle <= 0 || (handle & G2_INDEX_MASK) < 0 || (handle & G2_INDEX_MASK) >= MAX_G2_MODELS || mIds[handle & G2_INDEX_MASK] != handle)); + + return mInfos[handle & G2_INDEX_MASK]; + } + void TestAllAnims() + { + int j; + for (j=0;j &ghoul2=mInfos[j]; + int i; + for (i=0; i& DebugG2Info(int handle) +{ + return ((Ghoul2InfoArray*)(&TheGhoul2InfoArray()))->GetDebug(handle); +} + +CGhoul2Info& DebugG2InfoI(int handle, int item) +{ + return ((Ghoul2InfoArray*)(&TheGhoul2InfoArray()))->GetDebug(handle)[item]; +} + +void TestAllGhoul2Anims() +{ + ((Ghoul2InfoArray*)(&TheGhoul2InfoArray()))->TestAllAnims(); +} +#endif + +#define PERSISTENT_G2DATA "g2infoarray" + +void RestoreGhoul2InfoArray() +{ + if (singleton == NULL) + { + // Create the ghoul2 info array + TheGhoul2InfoArray(); + + size_t size; + const void *data = ri.PD_Load (PERSISTENT_G2DATA, &size); + if ( data == NULL ) + { + return; + } + +#ifdef _DEBUG + size_t read = +#endif // _DEBUG + singleton->Deserialize((const char*)data, size); + Z_Free((void*)data); +#ifdef _DEBUG + assert(read == size); +#endif + } +} + +void SaveGhoul2InfoArray() +{ + size_t size = singleton->GetSerializedSize(); + void *data = R_Malloc (size, TAG_GHOUL2, qfalse); + size_t written = singleton->Serialize ((char *)data); +#ifdef _DEBUG + assert(written == size); +#endif // _DEBUG + + if ( !ri.PD_Store (PERSISTENT_G2DATA, data, size) ) + { + Com_Printf (S_COLOR_RED "ERROR: Failed to store persistent renderer data.\n"); + } +} + +void Ghoul2InfoArray_Free(void) +{ + if(singleton) { + delete singleton; + singleton = NULL; + } +} + +// this is the ONLY function to read entity states directly +void G2API_CleanGhoul2Models(CGhoul2Info_v& ghoul2) +{ +#ifdef _G2_GORE + G2API_ClearSkinGore(ghoul2); +#endif + ghoul2.~CGhoul2Info_v(); +} + +qhandle_t G2API_PrecacheGhoul2Model(const char *fileName) +{ + return RE_RegisterModel(fileName); +} + +// initialise all that needs to be on a new Ghoul II model +int G2API_InitGhoul2Model(CGhoul2Info_v& ghoul2, const char* fileName, int modelIndex, qhandle_t customSkin, qhandle_t customShader, int modelFlags, int lodBias) +{ + int model = -1; + + G2ERROR(fileName && fileName[0], "NULL filename"); + + // are we actually asking for a model to be loaded. + if (!fileName || !fileName[0]) + { + assert(0); + return -1; + } + + // find a free spot in the list + for (model=0; model< ghoul2.size(); model++) + { + if (ghoul2[model].mModelindex == -1) + { + ghoul2[model]=CGhoul2Info(); + break; + } + } + if (model == ghoul2.size()) + { + assert(model < 8); //arb, just catching run-away models (why 4 instead of 8 in MP?) + CGhoul2Info info; + Q_strncpyz(info.mFileName, fileName, sizeof(info.mFileName)); + info.mModelindex = 0; + + if (G2_TestModelPointers(&info)) + { + ghoul2.push_back(CGhoul2Info()); + } + else + { + return -1; + } + } + + Q_strncpyz(ghoul2[model].mFileName, fileName, sizeof(ghoul2[model].mFileName)); + + ghoul2[model].mModelindex = model; + if (!G2_TestModelPointers(&ghoul2[model])) + { + ghoul2[model].mFileName[0]=0; + ghoul2[model].mModelindex = -1; + } + else + { + G2_Init_Bone_List(ghoul2[model].mBlist, ghoul2[model].aHeader->numBones); + G2_Init_Bolt_List(ghoul2[model].mBltlist); + ghoul2[model].mCustomShader = customShader; + ghoul2[model].mCustomSkin = customSkin; + ghoul2[model].mLodBias = lodBias; + ghoul2[model].mAnimFrameDefault = 0; + ghoul2[model].mFlags = 0; + + ghoul2[model].mModelBoltLink = -1; + } + return ghoul2[model].mModelindex; +} + +qboolean G2API_SetLodBias(CGhoul2Info *ghlInfo, int lodBias) +{ + G2ERROR(ghlInfo, "G2API_SetLodBias: NULL ghlInfo"); + if (G2_SetupModelPointers(ghlInfo)) + { + ghlInfo->mLodBias = lodBias; + return qtrue; + } + return qfalse; +} + +qboolean G2API_SetSkin(CGhoul2Info* ghlInfo, qhandle_t customSkin, qhandle_t renderSkin) +{ + G2ERROR(ghlInfo, "G2API_SetSkin: NULL ghlInfo"); + if (G2_SetupModelPointers(ghlInfo)) + { + ghlInfo->mCustomSkin = customSkin; +#ifndef JK2_MODE + if (renderSkin) + { + // this is going to set the surfs on/off matching the skin file + // header moved to tr_local.h, implemented in G2_surface.cpp + G2_SetSurfaceOnOffFromSkin( ghlInfo, renderSkin ); + } +#endif + return qtrue; + } + return qfalse; +} + +qboolean G2API_SetShader(CGhoul2Info *ghlInfo, qhandle_t customShader) +{ + G2ERROR(ghlInfo, "G2API_SetShader: NULL ghlInfo"); + if (ghlInfo) + { + ghlInfo->mCustomShader = customShader; + return qtrue; + } + return qfalse; +} + +qboolean G2API_SetSurfaceOnOff(CGhoul2Info* ghlInfo, const char* surfaceName, const int flags) +{ + G2ERROR(ghlInfo, "G2API_SetSurfaceOnOff: NULL ghlInfo"); + if (G2_SetupModelPointers(ghlInfo)) + { + G2ERROR(!(flags & ~(G2SURFACEFLAG_OFF | G2SURFACEFLAG_NODESCENDANTS)), "G2API_SetSurfaceOnOff Illegal Flags"); + // ensure we flush the cache + ghlInfo->mMeshFrameNum = 0; + return G2_SetSurfaceOnOff(ghlInfo, surfaceName, flags); + } + return qfalse; +} + +qboolean G2API_SetRootSurface(CGhoul2Info_v &ghoul2, const int modelIndex, const char *surfaceName) +{ + G2ERROR(ghoul2.IsValid(), "G2API_SetRootSurface: Invalid ghlInfo"); + G2ERROR(surfaceName, "G2API_SetRootSurface: Invalid surfaceName"); + + if (G2_SetupModelPointers(ghoul2)) + { + G2ERROR(modelIndex >= 0 && modelIndex < ghlInfo.size(), "Bad Model Index"); + if (modelIndex >= 0 && modelIndex < ghoul2.size()) + { + return G2_SetRootSurface(ghoul2, modelIndex, surfaceName); + } + } + + return qfalse; +} + +int G2API_AddSurface(CGhoul2Info *ghlInfo, int surfaceNumber, int polyNumber, float BarycentricI, float BarycentricJ, int lod ) +{ + if (G2_SetupModelPointers(ghlInfo)) + { + // ensure we flush the cache + ghlInfo->mMeshFrameNum = 0; + return G2_AddSurface(ghlInfo, surfaceNumber, polyNumber, BarycentricI, BarycentricJ, lod); + } + return -1; +} + +qboolean G2API_RemoveSurface(CGhoul2Info *ghlInfo, const int index) +{ + if (G2_SetupModelPointers(ghlInfo)) + { + // ensure we flush the cache + ghlInfo->mMeshFrameNum = 0; + return G2_RemoveSurface(ghlInfo->mSlist, index); + } + return qfalse; +} + +int G2API_GetParentSurface(CGhoul2Info *ghlInfo, const int index) +{ + if (G2_SetupModelPointers(ghlInfo)) + { + return G2_GetParentSurface(ghlInfo, index); + } + return -1; +} + +int G2API_GetSurfaceRenderStatus(CGhoul2Info* ghlInfo, const char* surfaceName) +{ + G2ERROR(surfaceName, "G2API_GetSurfaceRenderStatus: Invalid surfaceName"); + if (G2_SetupModelPointers(ghlInfo)) + { + return G2_IsSurfaceRendered(ghlInfo, surfaceName, ghlInfo->mSlist); + } + return -1; +} + +qboolean G2API_RemoveGhoul2Model(CGhoul2Info_v& ghlInfo, const int modelIndex) +{ + // sanity check + if (!ghlInfo.size() || (ghlInfo.size() <= modelIndex) || modelIndex < 0 || (ghlInfo[modelIndex].mModelindex < 0)) + { + // if we hit this assert then we are trying to delete a ghoul2 model on a ghoul2 instance that + // one way or another is already gone. + assert(0); + return qfalse; + } + + if (modelIndex < ghlInfo.size()) + { +#ifdef _G2_GORE + // Cleanup the gore attached to this model + if ( ghlInfo[modelIndex].mGoreSetTag ) + { + DeleteGoreSet ( ghlInfo[modelIndex].mGoreSetTag ); + ghlInfo[modelIndex].mGoreSetTag = 0; + } +#endif + + if (ghlInfo[modelIndex].mBoneCache) + { + RemoveBoneCache(ghlInfo[modelIndex].mBoneCache); + ghlInfo[modelIndex].mBoneCache=0; + } + + // clear out the vectors this model used. + ghlInfo[modelIndex].mBlist.clear(); + ghlInfo[modelIndex].mBltlist.clear(); + ghlInfo[modelIndex].mSlist.clear(); + + // set us to be the 'not active' state + ghlInfo[modelIndex].mModelindex = -1; + ghlInfo[modelIndex].mFileName[0] = 0; + ghlInfo[modelIndex] = CGhoul2Info(); + + int newSize = ghlInfo.size(); + + // ! the part below doesn't exist in SP Vanilla, but it makes sence ! + + // now look through the list from the back and see if there is a block of -1's we can resize off the end of the list + for (int i=ghlInfo.size()-1; i>-1; i--) + { + if (ghlInfo[i].mModelindex == -1) + { + newSize = i; + } + // once we hit one that isn't a -1, we are done. + else + { + break; + } + } + // do we need to resize? + if (newSize != ghlInfo.size()) + { + // yes, so lets do it + ghlInfo.resize(newSize); + } + } + + + return qtrue; +} + +int G2API_GetAnimIndex(CGhoul2Info* ghlInfo) +{ + return (ghlInfo) + ? ghlInfo->animModelIndexOffset + : 0; +} + +qboolean G2API_SetAnimIndex(CGhoul2Info* ghlInfo, const int index) +{ + // Is This A Valid G2 Model? + if (ghlInfo) + { + // Is This A New Anim Index? + if (ghlInfo->animModelIndexOffset != index) + { + ghlInfo->animModelIndexOffset = index; + // Clear anim size so SetupModelPointers recalcs + ghlInfo->currentAnimModelSize = 0; + + // Kill All Existing Animation, Blending, Etc. + //--------------------------------------------- + for (size_t index = 0; index < ghlInfo->mBlist.size(); index++) + { + ghlInfo->mBlist[index].flags &= ~(BONE_ANIM_TOTAL); + ghlInfo->mBlist[index].flags &= ~(BONE_ANGLES_TOTAL); + } + } + return qtrue; + } + return qfalse; +} + +//check if a bone exists on skeleton without actually adding to the bone list -rww +qboolean G2API_DoesBoneExist(CGhoul2Info_v& ghoul2, int modelIndex, const char *boneName) +{ + CGhoul2Info *ghlInfo = &ghoul2[modelIndex]; + + if (G2_SetupModelPointers(ghlInfo)) + { //model is valid + mdxaHeader_t *mdxa = ghlInfo->currentModel->data.gla; + if (mdxa) + { //get the skeleton data and iterate through the bones + int i; + mdxaSkel_t *skel; + mdxaSkelOffsets_t *offsets; + + offsets = (mdxaSkelOffsets_t *)((byte *)mdxa + sizeof(mdxaHeader_t)); + + for (i = 0; i < mdxa->numBones; i++) + { + skel = (mdxaSkel_t *)((byte *)mdxa + sizeof(mdxaHeader_t) + offsets->offsets[i]); + if (!Q_stricmp(skel->name, boneName)) + { //got it + return qtrue; + } + } + } + } + + //guess it doesn't exist + return qfalse; +} + + +qboolean G2API_SetBoneAnimIndex(CGhoul2Info *ghlInfo, const int index, const int startFrame, const int endFrame, const int flags, const float animSpeed, const int currentTime, const float setFrame, const int blendTime) +{ + //rww - RAGDOLL_BEGIN + if (ghlInfo && (ghlInfo->mFlags & GHOUL2_RAG_STARTED)) + { + return qfalse; + } + //rww - RAGDOLL_END + + qboolean ret = qfalse; + if (G2_SetupModelPointers(ghlInfo)) + { + G2ERROR(startFrame >= 0, "startframe < 0"); + G2ERROR(startFrame < ghlInfo->aHeader->numFrames, "startframe >= numframes"); + G2ERROR(endFrame > 0, "endframe <= 0"); + G2ERROR(endFrame <= ghlInfo->aHeader->numFrames, "endframe > numframes"); + G2ERROR(setFrame < ghlInfo->aHeader->numFrames, "setframe >= numframes"); + G2ERROR(setFrame == -1.0f || setFrame >= 0.0f, "setframe < 0 but not -1"); + + // this is cruel + if (startFrame < 0 || startFrame >= ghlInfo->aHeader->numFrames) + { + *(int*)&startFrame = 0; // cast away const + } + if (endFrame <= 0 || endFrame > ghlInfo->aHeader->numFrames) + { + *(int*)&endFrame = 1; + } + if (setFrame != -1.0f && (setFrame < 0.0f || setFrame >= (float)ghlInfo->aHeader->numFrames)) + { + *(float*)&setFrame = 0.0f; + } + ghlInfo->mSkelFrameNum = 0; + + G2ERROR(index >= 0 && index < (int)ghlInfo->mBlist.size(), va("Out of Range Bone Index (%s)", ghlInfo->mFileName)); + + if (index >= 0 && index < (int)ghlInfo->mBlist.size()) + { + G2ERROR(ghlInfo->mBlist[index].boneNumber >= 0, va("Bone Index is not Active (%s)", ghlInfo->mFileName)); + int a_currentTime = G2API_GetTime(currentTime); + + ret = G2_Set_Bone_Anim_Index(ghlInfo->mBlist, index, startFrame, endFrame, flags, animSpeed, a_currentTime, setFrame, blendTime, ghlInfo->aHeader->numFrames); + G2ANIM(ghlInfo, "G2API_SetBoneAnimIndex"); + } + } + + G2WARNING(ret, va("G2API_SetBoneAnimIndex Failed (%s)", ghlInfo->mFileName)); + return ret; +} + +qboolean G2API_SetBoneAnim(CGhoul2Info* ghlInfo, const char* boneName, const int startFrame, const int endFrame, + const int flags, const float animSpeed, const int currentTime, const float setFrame, const int blendTime) +{ + qboolean ret = qfalse; + G2ERROR(boneName, "G2API_SetBoneAnim: NULL boneName"); + if (boneName) + { + int a_startFrame = (startFrame < 0 || startFrame > 100000) ? 0 : startFrame; + int a_endFrame = (endFrame < 0 || endFrame > 100000) ? 1 : endFrame; + float a_setFrame = ((setFrame < 0.f && setFrame != -1.f) || setFrame > 100000) ? 0.f : setFrame; + + qboolean setPtrs = qfalse; + bool res = false; + + //rww - RAGDOLL_BEGIN + if (ghlInfo) + { + res = G2_SetupModelPointers(ghlInfo); + setPtrs = qtrue; + + if (res) + { + if (ghlInfo->mFlags & GHOUL2_RAG_STARTED) + { + return qfalse; + } + } + } + //rww - RAGDOLL_END + + if (!setPtrs) + { + res = G2_SetupModelPointers(ghlInfo); + } + + if (res && ghlInfo) + { + // ensure we flush the cache + ghlInfo->mSkelFrameNum = 0; + int a_currentTime = G2API_GetTime(currentTime); + return G2_Set_Bone_Anim(ghlInfo, ghlInfo->mBlist, boneName, a_startFrame, a_endFrame, flags, animSpeed, a_currentTime, a_setFrame, blendTime); + } + } + return qfalse; +} + +qboolean G2API_GetBoneAnim(CGhoul2Info* ghlInfo, const char* boneName, const int currentTime, float* currentFrame, + int* startFrame, int* endFrame, int* flags, float* animSpeed, qhandle_t* modelList) +{ + G2ERROR(boneName, "G2API_GetBoneAnim: NULL boneName"); + + assert(startFrame != endFrame); //this is bad + assert(startFrame != flags); //this is bad + assert(endFrame != flags); //this is bad + assert(currentFrame != animSpeed); //this is bad + + if (G2_SetupModelPointers(ghlInfo)) + { + int a_CurrentTime=G2API_GetTime(currentTime); +#ifdef _DEBUG + /* + assert(*endFrame>0); + assert(*endFrame<100000); + assert(*startFrame>=0); + assert(*startFrame<100000); + assert(*currentFrame>=0.0f); + assert(*currentFrame<100000.0f); + */ + if (*endFrame<1) + { + *endFrame=1; + } + if (*endFrame>100000) + { + *endFrame=1; + } + if (*startFrame<0) + { + *startFrame=0; + } + if (*startFrame>100000) + { + *startFrame=1; + } + if (*currentFrame<0.0f) + { + *currentFrame=0.0f; + } + if (*currentFrame>100000) + { + *currentFrame=1; + } +#endif + + qboolean ret = G2_Get_Bone_Anim(ghlInfo, ghlInfo->mBlist, boneName, a_CurrentTime, currentFrame, startFrame, endFrame, flags, animSpeed); + return ret; + } + + G2WARNING(ret, "G2API_GetBoneAnim Failed"); + return qfalse; +} + +qboolean G2API_GetBoneAnimIndex(CGhoul2Info* ghlInfo, const int iBoneIndex, const int currentTime, float* currentFrame, + int* startFrame, int* endFrame, int* flags, float* animSpeed, qhandle_t* modelList) +{ + qboolean ret = qfalse; + if (G2_SetupModelPointers(ghlInfo)) + { + int a_currentTime = G2API_GetTime(currentTime); + + if (iBoneIndex >= 0 && iBoneIndex < (int)ghlInfo->mBlist.size()) + { + if ((ghlInfo->mBlist[iBoneIndex].flags & (BONE_ANIM_OVERRIDE_LOOP | BONE_ANIM_OVERRIDE))) + { + int sf, ef; + ret = G2_Get_Bone_Anim_Index( + ghlInfo->mBlist,// boneInfo_v &blist, + iBoneIndex, // const int index, + a_currentTime, // const int a_currentTime, + currentFrame, // float *currentFrame, + &sf, // int *startFrame, + &ef, // int *endFrame, + flags, // int *flags, + animSpeed, // float *retAnimSpeed, + ghlInfo->aHeader->numFrames + ); + + G2ERROR(sf >= 0, "returning startframe<0"); + G2ERROR(sf < ghlInfo->aHeader->numFrames, "returning startframe>=numframes"); + G2ERROR(ef > 0, "returning endframe<=0"); + G2ERROR(ef <= ghlInfo->aHeader->numFrames, "returning endframe>numframes"); + + if (currentFrame) + { + G2ERROR(*currentFrame >= 0.0f, "returning currentframe<0"); + G2ERROR(((int)(*currentFrame)) < ghlInfo->aHeader->numFrames, "returning currentframe>=numframes"); + } + if (endFrame) + { + *endFrame = ef; + } + if (startFrame) + { + *startFrame = sf; + } + } + } + } + if (!ret) + { + if (endFrame) *endFrame = 1; + if (startFrame) *startFrame = 0; + if (flags) *flags = 0; + if (currentFrame) *currentFrame = 0.0f; + if (animSpeed) *animSpeed = 1.0f; + } + G2NOTE(ret, "G2API_GetBoneAnimIndex Failed"); + return ret; +} + +qboolean G2API_GetAnimRange(CGhoul2Info *ghlInfo, const char *boneName, int *startFrame, int *endFrame) +{ + G2ERROR(boneName, "G2API_GetAnimRange: NULL boneName"); + assert(startFrame != endFrame); //this is bad + + if (boneName && G2_SetupModelPointers(ghlInfo)) + { + qboolean ret=G2_Get_Bone_Anim_Range(ghlInfo, ghlInfo->mBlist, boneName, startFrame, endFrame); + G2ANIM(ghlInfo, "G2API_GetAnimRange"); +#ifdef _DEBUG + assert(*endFrame > 0); + assert(*endFrame < 100000); + assert(*startFrame >= 0); + assert(*startFrame < 100000); +#endif + return ret; + } + return qfalse; +} + +qboolean G2API_GetAnimRangeIndex(CGhoul2Info* ghlInfo, const int boneIndex, int* startFrame, int* endFrame) +{ + if (G2_SetupModelPointers(ghlInfo)) + { + G2ERROR(boneIndex >= 0 && boneIndex < (int)ghlInfo->mBlist.size(), "Bad Bone Index"); + if (boneIndex >= 0 && boneIndex < (int)ghlInfo->mBlist.size()) + { + return G2_Get_Bone_Anim_Range_Index(ghlInfo->mBlist, boneIndex, startFrame, endFrame); + } + } + return qfalse; +} + +qboolean G2API_PauseBoneAnim(CGhoul2Info *ghlInfo, const char *boneName, const int currentTime) +{ + G2ERROR(boneName, "G2API_PauseBoneAnim: NULL boneName"); + if (G2_SetupModelPointers(ghlInfo)) + { + int a_currentTime = G2API_GetTime(currentTime); + return G2_Pause_Bone_Anim(ghlInfo, ghlInfo->mBlist, boneName, a_currentTime); + } + G2WARNING(ret, "G2API_PauseBoneAnim Failed"); + return qfalse; +} + +qboolean G2API_PauseBoneAnimIndex(CGhoul2Info* ghlInfo, const int boneIndex, const int currentTime) +{ + if (G2_SetupModelPointers(ghlInfo)) + { + int a_currentTime = G2API_GetTime(currentTime); + + if (boneIndex >= 0 && boneIndex < (int)ghlInfo->mBlist.size()) + { + return G2_Pause_Bone_Anim_Index(ghlInfo->mBlist, boneIndex, a_currentTime, ghlInfo->aHeader->numFrames); + } + } + + G2WARNING(ret, "G2API_PauseBoneAnimIndex Failed"); + return qfalse; +} + +qboolean G2API_IsPaused(CGhoul2Info *ghlInfo, const char *boneName) +{ + G2ERROR(boneName, "G2API_IsPaused: NULL boneName"); + if (G2_SetupModelPointers(ghlInfo)) + { + return G2_IsPaused(ghlInfo, ghlInfo->mBlist, boneName); + } + return qfalse; +} + +qboolean G2API_StopBoneAnimIndex(CGhoul2Info *ghlInfo, const int index) +{ + G2ERROR(ghlInfo, "G2API_StopBoneAnimIndex: NULL ghlInfo"); + if (G2_SetupModelPointers(ghlInfo)) + { + if (index >= 0 && index < (int)ghlInfo->mBlist.size()) + { + return G2_Stop_Bone_Anim_Index(ghlInfo->mBlist, index); + } + } + return qfalse; +} + +qboolean G2API_StopBoneAnim(CGhoul2Info *ghlInfo, const char *boneName) +{ + G2ERROR(boneName, "G2API_StopBoneAnim: NULL boneName"); + if (G2_SetupModelPointers(ghlInfo)) + { + return G2_Stop_Bone_Anim(ghlInfo, ghlInfo->mBlist, boneName); + } + G2WARNING(ret, "G2API_StopBoneAnim Failed"); + return qfalse; +} + +qboolean G2API_SetBoneAnglesIndex( + CGhoul2Info *ghlInfo, const int index, const vec3_t angles, const int flags, + const Eorientations yaw, const Eorientations pitch, const Eorientations roll, + qhandle_t *modelList, int blendTime, int currentTime) +{ + qboolean setPtrs = qfalse; + bool res = false; + + if (ghlInfo) + { + res = G2_SetupModelPointers(ghlInfo); + setPtrs = qtrue; + + if (res) + { + if (ghlInfo->mFlags & GHOUL2_RAG_STARTED) + { + return qfalse; + } + } + } + + if (!setPtrs) + { + res = G2_SetupModelPointers(ghlInfo); + } + + if (res) + { + // ensure we flush the cache + ghlInfo->mSkelFrameNum = 0; + return G2_Set_Bone_Angles_Index(ghlInfo, ghlInfo->mBlist, index, angles, flags, yaw, pitch, roll, blendTime, currentTime); + } + + return qfalse; +} + +qboolean G2API_SetBoneAngles(CGhoul2Info* ghlInfo, const char* boneName, const vec3_t angles, const int flags, + const Eorientations up, const Eorientations left, const Eorientations forward, qhandle_t* modelList, int blendTime, int currentTime) +{ + //rww - RAGDOLL_BEGIN + if (ghlInfo && ghlInfo->mFlags & GHOUL2_RAG_STARTED) + { + return qfalse; + } + //rww - RAGDOLL_END + + qboolean ret = qfalse; + + G2ERROR(boneName, "G2API_SetBoneAngles: NULL boneName"); + if (boneName && G2_SetupModelPointers(ghlInfo)) + { + currentTime = G2API_GetTime(currentTime); + // ensure we flush the cache + ghlInfo->mSkelFrameNum = 0; + ret = G2_Set_Bone_Angles(ghlInfo, ghlInfo->mBlist, boneName, angles, flags, up, left, forward, blendTime, currentTime); + } + + G2WARNING(ret, "G2API_SetBoneAngles Failed"); + return ret; +} + +qboolean G2API_SetBoneAnglesMatrixIndex( + CGhoul2Info *ghlInfo, const int index, const mdxaBone_t &matrix, const int flags, + qhandle_t *modelList, int blendTime, int currentTime) +{ + if (G2_SetupModelPointers(ghlInfo)) + { + currentTime = G2API_GetTime(currentTime); + // ensure we flush the cache + ghlInfo->mSkelFrameNum = 0; + G2ERROR(index >= 0 && index < (int)ghlInfo->mBlist.size(), "Bad Bone Index"); + if (index >= 0 && index < (int)ghlInfo->mBlist.size()) + { + return G2_Set_Bone_Angles_Matrix_Index(ghlInfo->mBlist, index, matrix, flags, blendTime, currentTime); + } + } + return qfalse; +} + +qboolean G2API_SetBoneAnglesMatrix( + CGhoul2Info *ghlInfo, const char *boneName, const mdxaBone_t &matrix, const int flags, + qhandle_t *modelList, int blendTime, int currentTime) +{ + G2ERROR(boneName, "G2API_SetBoneAnglesMatrix: NULL boneName"); + if (G2_SetupModelPointers(ghlInfo)) + { + currentTime = G2API_GetTime(currentTime); + // ensure we flush the cache + ghlInfo->mSkelFrameNum = 0; + return G2_Set_Bone_Angles_Matrix(ghlInfo, ghlInfo->mBlist, boneName, matrix, flags, blendTime, currentTime); + } + return qfalse; +} + +qboolean G2API_StopBoneAnglesIndex(CGhoul2Info *ghlInfo, const int index) +{ + if (G2_SetupModelPointers(ghlInfo)) + { + // ensure we flush the cache + ghlInfo->mSkelFrameNum = 0; + G2ERROR(index >= 0 && index < (int)ghlInfo->mBlist.size(), "Bad Bone Index"); + if (index >= 0 && index < (int)ghlInfo->mBlist.size()) + { + return G2_Stop_Bone_Angles_Index(ghlInfo->mBlist, index); + } + } + return qfalse; +} + +qboolean G2API_StopBoneAngles(CGhoul2Info *ghlInfo, const char *boneName) +{ + if (boneName && G2_SetupModelPointers(ghlInfo)) + { + // ensure we flush the cache + ghlInfo->mSkelFrameNum = 0; + return G2_Stop_Bone_Angles( + ghlInfo, ghlInfo->mBlist, boneName); + } + return qfalse; +} + +void G2API_AbsurdSmoothing(CGhoul2Info_v &ghoul2, qboolean status) +{ + assert(ghoul2.size()); + CGhoul2Info *ghlInfo = &ghoul2[0]; +#ifndef REND2_SP + if (status) + { //turn it on + ghlInfo->mFlags |= GHOUL2_CRAZY_SMOOTH; + } + else + { //off + ghlInfo->mFlags &= ~GHOUL2_CRAZY_SMOOTH; + } +#endif +} + +//rww - RAGDOLL_BEGIN +class CRagDollParams; +void G2_SetRagDoll(CGhoul2Info_v &ghoul2V,CRagDollParams *parms); +void G2API_SetRagDoll(CGhoul2Info_v &ghoul2,CRagDollParams *parms) +{ + G2_SetRagDoll(ghoul2,parms); +} + +void G2_ResetRagDoll(CGhoul2Info_v &ghoul2V); +void G2API_ResetRagDoll(CGhoul2Info_v &ghoul2) +{ + G2_ResetRagDoll(ghoul2); +} +//rww - RAGDOLL_END + +qboolean G2API_RemoveBone(CGhoul2Info* ghlInfo, const char* boneName) +{ + G2ERROR(boneName, "G2API_RemoveBone: NULL boneName"); + + if (boneName && G2_SetupModelPointers(ghlInfo)) + { + // ensure we flush the cache + ghlInfo->mSkelFrameNum = 0; + return G2_Remove_Bone(ghlInfo, ghlInfo->mBlist, boneName); + } + return qfalse; +} + +//rww - RAGDOLL_BEGIN +#ifdef _DEBUG +extern int ragTraceTime; +extern int ragSSCount; +extern int ragTraceCount; +#endif + +// This is G2API_AnimateG2Models +void G2API_AnimateG2ModelsRag(CGhoul2Info_v &ghoul2, int AcurrentTime, CRagDollUpdateParams *params) +{ + int model; + int currentTime = G2API_GetTime(AcurrentTime); + +#ifdef _DEBUG + ragTraceTime = 0; + ragSSCount = 0; + ragTraceCount = 0; +#endif + + // Walk the list and find all models that are active + for (model = 0; model < ghoul2.size(); model++) + { + if (ghoul2[model].mModel) + { + G2_Animate_Bone_List(ghoul2, currentTime, model, params); + } + } +} +// rww - RAGDOLL_END + +int G2_Find_Bone_Rag( + CGhoul2Info *ghlInfo, boneInfo_v &blist, const char *boneName); +#define RAG_PCJ (0x00001) +#define RAG_EFFECTOR (0x00100) + +static boneInfo_t* G2_GetRagBoneConveniently(CGhoul2Info_v &ghoul2, const char *boneName) +{ + assert(ghoul2.size()); + CGhoul2Info *ghlInfo = &ghoul2[0]; + + if (!(ghlInfo->mFlags & GHOUL2_RAG_STARTED)) + { // can't do this if not in ragdoll + return NULL; + } + + int boneIndex = G2_Find_Bone_Rag(ghlInfo, ghlInfo->mBlist, boneName); + + if (boneIndex < 0) + { // bad bone specification + return NULL; + } + + boneInfo_t *bone = &ghlInfo->mBlist[boneIndex]; + + if (!(bone->flags & BONE_ANGLES_RAGDOLL)) + { // only want to return rag bones + return NULL; + } + + return bone; +} + +qboolean G2API_RagPCJConstraint(CGhoul2Info_v &ghoul2, const char *boneName, vec3_t min, vec3_t max) +{ + boneInfo_t *bone = G2_GetRagBoneConveniently(ghoul2, boneName); + + if (!bone) + { + return qfalse; + } + + if (!(bone->RagFlags & RAG_PCJ)) + { // this function is only for PCJ bones + return qfalse; + } + + VectorCopy(min, bone->minAngles); + VectorCopy(max, bone->maxAngles); + + return qtrue; +} + +qboolean G2API_RagPCJGradientSpeed(CGhoul2Info_v &ghoul2, const char *boneName, const float speed) +{ + boneInfo_t *bone = G2_GetRagBoneConveniently(ghoul2, boneName); + + if (!bone) + { + return qfalse; + } + + if (!(bone->RagFlags & RAG_PCJ)) + { // this function is only for PCJ bones + return qfalse; + } + + bone->overGradSpeed = speed; + + return qtrue; +} + +qboolean G2API_RagEffectorGoal(CGhoul2Info_v &ghoul2, const char *boneName, vec3_t pos) +{ + boneInfo_t *bone = G2_GetRagBoneConveniently(ghoul2, boneName); + + if (!bone) + { + return qfalse; + } + + if (!(bone->RagFlags & RAG_EFFECTOR)) + { // this function is only for effectors + return qfalse; + } + + if (!pos) + { // go back to none in case we have one then + bone->hasOverGoal = false; + } + else + { + VectorCopy(pos, bone->overGoalSpot); + bone->hasOverGoal = true; + } + return qtrue; +} + +qboolean G2API_GetRagBonePos(CGhoul2Info_v &ghoul2, const char *boneName, vec3_t pos, vec3_t entAngles, vec3_t entPos, vec3_t entScale) +{ + return qfalse; +} + +qboolean G2API_RagEffectorKick(CGhoul2Info_v &ghoul2, const char *boneName, vec3_t velocity) +{ + boneInfo_t *bone = G2_GetRagBoneConveniently(ghoul2, boneName); + + if (!bone) + { + return qfalse; + } + + if (!(bone->RagFlags & RAG_EFFECTOR)) + { //this function is only for effectors + return qfalse; + } + + bone->epVelocity[2] = 0; + VectorAdd(bone->epVelocity, velocity, bone->epVelocity); + bone->physicsSettled = false; + + return qtrue; +} + +qboolean G2API_RagForceSolve(CGhoul2Info_v &ghoul2, qboolean force) +{ + assert(ghoul2.size()); + CGhoul2Info *ghlInfo = &ghoul2[0]; + + if (!(ghlInfo->mFlags & GHOUL2_RAG_STARTED)) + { //can't do this if not in ragdoll + return qfalse; + } + + if (force) + { + ghlInfo->mFlags |= GHOUL2_RAG_FORCESOLVE; + } + else + { + ghlInfo->mFlags &= ~GHOUL2_RAG_FORCESOLVE; + } + + return qtrue; +} + +qboolean G2_SetBoneIKState(CGhoul2Info_v &ghoul2, int time, const char *boneName, int ikState, sharedSetBoneIKStateParams_t *params); + +qboolean G2API_SetBoneIKState(CGhoul2Info_v &ghoul2, int time, const char *boneName, int ikState, sharedSetBoneIKStateParams_t *params) +{ + return G2_SetBoneIKState(ghoul2, time, boneName, ikState, params); +} + +qboolean G2_IKMove(CGhoul2Info_v &ghoul2, int time, sharedIKMoveParams_t *params); + +qboolean G2API_IKMove(CGhoul2Info_v &ghoul2, int time, sharedIKMoveParams_t *params) +{ + return G2_IKMove(ghoul2, time, params); +} + +qboolean G2API_RemoveBolt(CGhoul2Info *ghlInfo, const int index) +{ + if (G2_SetupModelPointers(ghlInfo)) + { + return G2_Remove_Bolt(ghlInfo->mBltlist, index); + } + return qfalse; +} + +int G2API_AddBolt(CGhoul2Info* ghlInfo, const char* boneName) +{ + // assert(ghoul2.size()>modelIndex); + if (boneName && G2_SetupModelPointers(ghlInfo)) + { + return G2_Add_Bolt(ghlInfo, ghlInfo->mBltlist, ghlInfo->mSlist, boneName); + } + return -1; +} + +int G2API_AddBoltSurfNum(CGhoul2Info *ghlInfo, const int surfIndex) +{ + if (G2_SetupModelPointers(ghlInfo)) + { + return G2_Add_Bolt_Surf_Num( + ghlInfo, ghlInfo->mBltlist, ghlInfo->mSlist, surfIndex); + } + return -1; +} + +qboolean G2API_AttachG2Model(CGhoul2Info* ghlInfo, CGhoul2Info* ghlInfoTo, int toBoltIndex, int toModel) +{ + qboolean ret = qfalse; + + if (G2_SetupModelPointers(ghlInfo) && G2_SetupModelPointers(ghlInfoTo)) + { + G2ERROR(toBoltIndex >= 0 && toBoltIndex < (int)ghlInfoTo->mBltlist.size(), "Invalid Bolt Index"); + G2ERROR(ghlInfoTo->mBltlist.size() > 0, "Empty Bolt List"); + + assert(toBoltIndex >= 0); + + if (toBoltIndex >= 0 && ghlInfoTo->mBltlist.size()) + { + // make sure we have a model to attach, a model to attach to, and a bolt on that model + if (((ghlInfoTo->mBltlist[toBoltIndex].boneNumber != -1) || (ghlInfoTo->mBltlist[toBoltIndex].surfaceNumber != -1))) + { + // encode the bolt address into the model bolt link + toModel &= MODEL_AND; + toBoltIndex &= BOLT_AND; + ghlInfo->mModelBoltLink = (toModel << MODEL_SHIFT) | (toBoltIndex << BOLT_SHIFT); + ret = qtrue; + } + } + } + G2WARNING(ret, "G2API_AttachG2Model Failed"); + return ret; +} + +void G2API_SetBoltInfo(CGhoul2Info_v &ghoul2, int modelIndex, int boltInfo) +{ + if (ghoul2.size() > modelIndex) + { + ghoul2[modelIndex].mModelBoltLink = boltInfo; + } +} + +qboolean G2API_DetachG2Model(CGhoul2Info *ghlInfo) +{ + if (G2_SetupModelPointers(ghlInfo)) + { + ghlInfo->mModelBoltLink = -1; + return qtrue; + } + return qfalse; +} + +qboolean G2API_AttachEnt(int* boltInfo, CGhoul2Info* ghlInfoTo, int toBoltIndex, int entNum, int toModelNum) +{ + if (boltInfo && G2_SetupModelPointers(ghlInfoTo)) + { + // make sure we have a model to attach, a model to attach to, and a + // bolt on that model + if (ghlInfoTo->mBltlist.size() && + ((ghlInfoTo->mBltlist[toBoltIndex].boneNumber != -1) || + (ghlInfoTo->mBltlist[toBoltIndex].surfaceNumber != -1))) + { + // encode the bolt address into the model bolt link + toModelNum &= MODEL_AND; + toBoltIndex &= BOLT_AND; + entNum &= ENTITY_AND; + *boltInfo = (toBoltIndex << BOLT_SHIFT) | + (toModelNum << MODEL_SHIFT) | + (entNum << ENTITY_SHIFT); + return qtrue; + } + } + return qfalse; +} + +void G2API_DetachEnt(int* boltInfo) +{ + G2ERROR(boltInfo, "G2API_DetachEnt: NULL boltInfo"); + if (boltInfo) + { + *boltInfo = 0; + } +} + +bool G2_NeedsRecalc(CGhoul2Info *ghlInfo, int frameNum); + +qboolean G2API_GetBoltMatrix(CGhoul2Info_v& ghoul2, const int modelIndex, const int boltIndex, mdxaBone_t* matrix, + const vec3_t angles, const vec3_t position, const int frameNum, qhandle_t* modelList, const vec3_t scale) +{ + G2ERROR(ghoul2.IsValid(), "Invalid ghlInfo"); + G2ERROR(matrix, "NULL matrix"); + G2ERROR(modelIndex >= 0 && modelIndex < ghoul2.size(), "Invalid ModelIndex"); + const static mdxaBone_t identityMatrix = + { + { + {0.0f, -1.0f, 0.0f, 0.0f}, + {1.0f, 0.0f, 0.0f, 0.0f}, + {0.0f, 0.0f, 1.0f, 0.0f} + } + }; + + G2_GenerateWorldMatrix(angles, position); + if (G2_SetupModelPointers(ghoul2)) + { + if (matrix && modelIndex >= 0 && modelIndex < ghoul2.size()) + { + int tframeNum = G2API_GetTime(frameNum); + CGhoul2Info *ghlInfo = &ghoul2[modelIndex]; + G2ERROR + (boltIndex >= 0 && (boltIndex < ghlInfo->mBltlist.size()), + va("Invalid Bolt Index (%d:%s)", + boltIndex, + ghlInfo->mFileName)); + + if (boltIndex >= 0 && ghlInfo && (boltIndex < (int)ghlInfo->mBltlist.size())) + { + mdxaBone_t bolt; + + if (G2_NeedsRecalc(ghlInfo, tframeNum)) + { + G2_ConstructGhoulSkeleton(ghoul2, tframeNum, true, scale); + } + + G2_GetBoltMatrixLow(*ghlInfo, boltIndex, scale, bolt); + + // scale the bolt position by the scale factor for this model + // since at this point its still in model space + if (scale[0]) + { + bolt.matrix[0][3] *= scale[0]; + } + + if (scale[1]) + { + bolt.matrix[1][3] *= scale[1]; + } + + if (scale[2]) + { + bolt.matrix[2][3] *= scale[2]; + } + + VectorNormalize((float *)&bolt.matrix[0]); + VectorNormalize((float *)&bolt.matrix[1]); + VectorNormalize((float *)&bolt.matrix[2]); + + Mat3x4_Multiply(matrix, &worldMatrix, &bolt); +#if G2API_DEBUG + for (int i = 0; i < 3; i++) + { + for (int j = 0; j < 4; j++) + { + assert(!_isnan(matrix->matrix[i][j])); + } + } +#endif // _DEBUG + G2ANIM(ghlInfo, "G2API_GetBoltMatrix"); + + return qtrue; + } + } + } + else + { + G2WARNING(0, "G2API_GetBoltMatrix Failed on empty or bad model"); + } + Mat3x4_Multiply(matrix, &worldMatrix, (mdxaBone_t *)&identityMatrix); + return qfalse; +} + +void G2API_ListSurfaces(CGhoul2Info *ghlInfo) +{ + if (G2_SetupModelPointers(ghlInfo)) + { + G2_List_Model_Surfaces(ghlInfo->mFileName); + } +} + +void G2API_ListBones(CGhoul2Info *ghlInfo, int frame) +{ + if (G2_SetupModelPointers(ghlInfo)) + { + G2_List_Model_Bones(ghlInfo->mFileName, frame); + } +} + +// decide if we have Ghoul2 models associated with this ghoul list or not +qboolean G2API_HaveWeGhoul2Models(CGhoul2Info_v &ghoul2) +{ + if (ghoul2.size()) + { + for (int i = 0; i < ghoul2.size(); i++) + { + if (ghoul2[i].mModelindex != -1) + { + return qtrue; + } + } + } + return qfalse; +} + +// run through the Ghoul2 models and set each of the mModel values to the +// correct one from the cgs.gameModel offset lsit +void G2API_SetGhoul2ModelIndexes(CGhoul2Info_v &ghoul2, qhandle_t *modelList, qhandle_t *skinList) +{ + G2ERROR(ghoul2.IsValid(), "G2API_SetGhoul2ModelIndexes: Invalid ghlInfo"); + + for (int i = 0; i < ghoul2.size(); i++) + { + if (ghoul2[i].mModelindex != -1) + { + ghoul2[i].mSkin = skinList[ghoul2[i].mCustomSkin]; + } + } +} + +char *G2API_GetAnimFileNameIndex(qhandle_t modelIndex) +{ + model_t* mod_m = R_GetModelByHandle(modelIndex); + + G2ERROR(mod_m && mod_m->data.glm, "G2API_GetAnimFileNameIndex: Bad Model"); + if (mod_m && mod_m->data.glm && mod_m->data.glm->header) + { + return mod_m->data.glm->header->animName; + } + return ""; +} + +// As above, but gets the internal embedded name, not the name of the disk file. +// This is needed for some unfortunate jiggery-hackery to do with frameskipping & the animevents.cfg file +char* G2API_GetAnimFileInternalNameIndex(qhandle_t modelIndex) +{ + model_t* mod_a = R_GetModelByHandle(modelIndex); + + G2ERROR(mod_a && mod_a->data.gla, "G2API_GetAnimFileInternalNameIndex: Bad Model"); + if (mod_a && mod_a->data.gla) + { + return mod_a->data.gla->name; + } + return ""; +} + +qboolean G2API_GetAnimFileName(CGhoul2Info *ghlInfo, char **filename) +{ + if (G2_SetupModelPointers(ghlInfo)) + { + return G2_GetAnimFileName(ghlInfo->mFileName, filename); + } + return qfalse; +} + +/* +======================= +SV_QsortEntityNumbers +======================= +*/ +static int QDECL QsortDistance(const void *a, const void *b) +{ + const float &ea = ((CCollisionRecord*)a)->mDistance; + const float &eb = ((CCollisionRecord*)b)->mDistance; + return (ea < eb) ? -1 : 1; +} + +void G2API_CollisionDetect( + CCollisionRecord* collRecMap, CGhoul2Info_v& ghoul2, + const vec3_t angles, const vec3_t position, int frameNumber, int entNum, + vec3_t rayStart, vec3_t rayEnd, vec3_t scale, + CMiniHeap* G2VertSpace, EG2_Collision eG2TraceType, int useLod, float fRadius) +{ + // not exactly correct, but doesn't matter + G2ERROR(ghoul2.IsValid(), "G2API_CollisionDetect: Invalid ghlInfo"); + G2ERROR(collRecMap, "G2API_CollisionDetect: NULL Collision Rec"); + + if (G2_SetupModelPointers(ghoul2) && collRecMap) + { + frameNumber = G2API_GetTime(frameNumber); + vec3_t transRayStart, transRayEnd; + + // make sure we have transformed the whole skeletons for each model + G2_ConstructGhoulSkeleton(ghoul2, frameNumber, true, scale); + + // pre generate the world matrix - used to transform the incoming ray + G2_GenerateWorldMatrix(angles, position); + + ri.GetG2VertSpaceServer()->ResetHeap(); + +// now having done that, time to build the model +#ifdef _G2_GORE + G2_TransformModel(ghoul2, frameNumber, scale, ri.GetG2VertSpaceServer(), useLod, false); +#else + G2_TransformModel(ghoul2, frameNumber, scale, ri.GetG2VertSpaceServer(), useLod); +#endif + + // model is built. Lets check to see if any triangles are actually hit. + // first up, translate the ray to model space + TransformAndTranslatePoint(rayStart, transRayStart, &worldMatrixInv); + TransformAndTranslatePoint(rayEnd, transRayEnd, &worldMatrixInv); + + // now walk each model and check the ray against each poly - sigh, this is SO expensive. I wish there was a better way to do this. +#ifdef _G2_GORE + G2_TraceModels(ghoul2, transRayStart, transRayEnd, collRecMap, entNum, eG2TraceType, useLod, fRadius, 0, 0, 0, 0, 0, qfalse); +#else + G2_TraceModels(ghoul2, transRayStart, transRayEnd, collRecMap, entNum, eG2TraceType, useLod, fRadius); +#endif + + ri.GetG2VertSpaceServer()->ResetHeap(); + // now sort the resulting array of collision records so they are distance ordered + qsort(collRecMap, MAX_G2_COLLISIONS, sizeof(CCollisionRecord), QsortDistance); + G2ANIM(ghoul2, "G2API_CollisionDetect"); + } +} + +qboolean G2API_SetGhoul2ModelFlags(CGhoul2Info *ghlInfo, const int flags) +{ + if (G2_SetupModelPointers(ghlInfo)) + { + ghlInfo->mFlags &= GHOUL2_NEWORIGIN; + ghlInfo->mFlags |= flags; + return qtrue; + } + return qfalse; +} + +int G2API_GetGhoul2ModelFlags(CGhoul2Info *ghlInfo) +{ + if (G2_SetupModelPointers(ghlInfo)) + { + return (ghlInfo->mFlags & ~GHOUL2_NEWORIGIN); + } + return 0; +} + +// given a boltmatrix, return in vec a normalised vector for the axis requested in flags +void G2API_GiveMeVectorFromMatrix(mdxaBone_t& boltMatrix, Eorientations flags, vec3_t& vec) +{ + switch (flags) + { + case ORIGIN: + vec[0] = boltMatrix.matrix[0][3]; + vec[1] = boltMatrix.matrix[1][3]; + vec[2] = boltMatrix.matrix[2][3]; + break; + case POSITIVE_Y: + vec[0] = boltMatrix.matrix[0][1]; + vec[1] = boltMatrix.matrix[1][1]; + vec[2] = boltMatrix.matrix[2][1]; + break; + case POSITIVE_X: + vec[0] = boltMatrix.matrix[0][0]; + vec[1] = boltMatrix.matrix[1][0]; + vec[2] = boltMatrix.matrix[2][0]; + break; + case POSITIVE_Z: + vec[0] = boltMatrix.matrix[0][2]; + vec[1] = boltMatrix.matrix[1][2]; + vec[2] = boltMatrix.matrix[2][2]; + break; + case NEGATIVE_Y: + vec[0] = -boltMatrix.matrix[0][1]; + vec[1] = -boltMatrix.matrix[1][1]; + vec[2] = -boltMatrix.matrix[2][1]; + break; + case NEGATIVE_X: + vec[0] = -boltMatrix.matrix[0][0]; + vec[1] = -boltMatrix.matrix[1][0]; + vec[2] = -boltMatrix.matrix[2][0]; + break; + case NEGATIVE_Z: + vec[0] = -boltMatrix.matrix[0][2]; + vec[1] = -boltMatrix.matrix[1][2]; + vec[2] = -boltMatrix.matrix[2][2]; + break; + } +} + +// copy a model from one ghoul2 instance to another, and reset the root surface on the new model if need be +// NOTE if modelIndex = -1 then copy all the models +void G2API_CopyGhoul2Instance(CGhoul2Info_v &g2From, CGhoul2Info_v &g2To, int modelIndex) +{ + G2ERROR(ghoul2From.IsValid(),"G2API_CopyGhoul2Instance: Invalid ghlInfo"); + + if (g2From.IsValid()) + { + g2To.DeepCopy(g2From); + +#ifdef _G2_GORE //check through gore stuff then, as well. + int model = 0; + + //(since we are sharing this gore set with the copied instance we will have to increment + //the reference count - if the goreset is "removed" while the refcount is > 0, the refcount + //is decremented to avoid giving other instances an invalid pointer -rww) + while (model < g2To.size()) + { + if (g2To[model].mGoreSetTag) + { + CGoreSet* gore = FindGoreSet(g2To[model].mGoreSetTag); + assert(gore); + if (gore) + { + gore->mRefCount++; + } + } + + model++; + } +#endif + G2ANIM(ghoul2From, "G2API_CopyGhoul2Instance (source)"); + G2ANIM(ghoul2To, "G2API_CopyGhoul2Instance (dest)"); + } +} + +char* G2API_GetSurfaceName(CGhoul2Info* ghlInfo, int surfNumber) +{ + static char noSurface[1] = ""; + + if (G2_SetupModelPointers(ghlInfo)) + { + model_t *mod = (model_t *)ghlInfo->currentModel; + mdxmSurface_t* surf = 0; + mdxmSurfHierarchy_t* surfInfo = 0; + mdxmHeader_t* mdxm; + + mdxm = mod->data.glm->header; + + //ok, I guess it's semi-valid for the user to be passing in surface > numSurfs because they don't know how many surfs a model + //may have.. but how did they get that surf index to begin with? Oh well. + if (surfNumber < 0 || surfNumber >= mdxm->numSurfaces) + { + Com_Printf("G2API_GetSurfaceName: You passed in an invalid surface number (%i) for model %s.\n", surfNumber, ghlInfo->mFileName); + return noSurface; + } + + surf = (mdxmSurface_t*)G2_FindSurface(mod, surfNumber, 0); + if (surf) + { + mdxmHierarchyOffsets_t* surfIndexes = (mdxmHierarchyOffsets_t*)((byte*)ghlInfo->currentModel->data.glm->header + sizeof(mdxmHeader_t)); + surfInfo = (mdxmSurfHierarchy_t*)((byte*)surfIndexes + surfIndexes->offsets[surf->thisSurfaceIndex]); + return surfInfo->name; + } + } + return noSurface; +} + + +int G2API_GetSurfaceIndex(CGhoul2Info *ghlInfo, const char *surfaceName) +{ + G2ERROR(surfaceName, "G2API_GetSurfaceIndex: NULL surfaceName"); + + if (G2_SetupModelPointers(ghlInfo)) + { + return G2_GetSurfaceIndex(ghlInfo, surfaceName); + } + return -1; +} + +char* G2API_GetGLAName(CGhoul2Info* ghlInfo) +{ + if (G2_SetupModelPointers(ghlInfo)) + { + assert(ghlInfo && ghlInfo->currentModel->data.glm); + return (char*)ghlInfo->aHeader->name; + } + return NULL; +} + +qboolean G2API_SetNewOrigin(CGhoul2Info* ghlInfo, const int boltIndex) +{ + if (G2_SetupModelPointers(ghlInfo)) + { + // check for valid boltIndex before applying new origin + if (boltIndex >= 0 && boltIndex < (int)ghlInfo->mBltlist.size()) + { + ghlInfo->mNewOrigin = boltIndex; + ghlInfo->mFlags |= GHOUL2_NEWORIGIN; + } + return qtrue; + } + return qfalse; +} + +int G2API_GetBoneIndex(CGhoul2Info *ghlInfo, const char *boneName, qboolean bAddIfNotFound) +{ + G2ERROR(boneName, "G2API_GetBoneIndex: NULL boneName"); + if (boneName && G2_SetupModelPointers(ghlInfo)) + { + return G2_Get_Bone_Index(ghlInfo, boneName, bAddIfNotFound); + } + return -1; +} + +void G2API_SaveGhoul2Models(CGhoul2Info_v &ghoul2) +{ + G2_SaveGhoul2Models(ghoul2); + G2ANIM(ghoul2, "G2API_SaveGhoul2Models"); +} + +void G2API_LoadGhoul2Models(CGhoul2Info_v &ghoul2, char *buffer) +{ + G2_LoadGhoul2Model(ghoul2, buffer); + G2ANIM(ghoul2, "G2API_LoadGhoul2Models"); +} + +// this is kinda sad, but I need to call the destructor in this module (exe), not the game.dll... +// +void G2API_LoadSaveCodeDestructGhoul2Info(CGhoul2Info_v &ghoul2) +{ + +#ifdef _G2_GORE + G2API_ClearSkinGore ( ghoul2 ); +#endif + ghoul2.~CGhoul2Info_v(); // so I can load junk over it then memset to 0 without orphaning +} + +//see if surfs have any shader info... +qboolean G2API_SkinlessModel(CGhoul2Info_v& ghoul2, int modelIndex) +{ + CGhoul2Info *g2 = &ghoul2[modelIndex]; + + if (G2_SetupModelPointers(g2)) + { + model_t *mod = (model_t *)g2->currentModel; + + if (mod && + mod->data.glm && + mod->data.glm->header) + { + mdxmSurfHierarchy_t *surf; + int i; + mdxmHeader_t *mdxm = mod->data.glm->header; + + surf = (mdxmSurfHierarchy_t *) ( (byte *)mdxm + mdxm->ofsSurfHierarchy ); + + for (i = 0; i < mdxm->numSurfaces; i++) + { + if (surf->shader[0]) + { //found a surface with a shader name, ok. + return qfalse; + } + + surf = (mdxmSurfHierarchy_t *)( (byte *)surf + (intptr_t)( &((mdxmSurfHierarchy_t *)0)->childIndexes[ surf->numChildren ] )); + } + } + } + + //found nothing. + return qtrue; +} + +int G2API_Ghoul2Size(CGhoul2Info_v &ghoul2) +{ + return ghoul2.size(); +} + +//#ifdef _SOF2 +#ifdef _G2_GORE +void ResetGoreTag(); // put here to reduce coupling + +//way of seeing how many marks are on a model currently -rww +int G2API_GetNumGoreMarks(CGhoul2Info_v& ghoul2, int modelIndex) +{ + CGhoul2Info *g2 = &ghoul2[modelIndex]; + + if (g2->mGoreSetTag) + { + CGoreSet *goreSet = FindGoreSet(g2->mGoreSetTag); + + if (goreSet) + { + return goreSet->mGoreRecords.size(); + } + } + + return 0; +} + +void G2API_ClearSkinGore ( CGhoul2Info_v &ghoul2 ) +{ + for (int i = 0; i < ghoul2.size(); i++) + { + if (ghoul2[i].mGoreSetTag) + { + DeleteGoreSet(ghoul2[i].mGoreSetTag); + ghoul2[i].mGoreSetTag = 0; + } + } +} + +extern int G2_DecideTraceLod(CGhoul2Info &ghoul2, int useLod); +void G2API_AddSkinGore(CGhoul2Info_v &ghoul2,SSkinGoreData &gore) +{ + if (VectorLength(gore.rayDirection)<.1f) + { + assert(0); // can't add gore without a shot direction + return; + } + + // make sure we have transformed the whole skeletons for each model + G2_ConstructGhoulSkeleton(ghoul2, gore.currentTime, true, gore.scale); + + // pre generate the world matrix - used to transform the incoming ray + G2_GenerateWorldMatrix(gore.angles, gore.position); + + // first up, translate the ray to model space + vec3_t transRayDirection, transHitLocation; + TransformAndTranslatePoint(gore.hitLocation, transHitLocation, &worldMatrixInv); + TransformPoint(gore.rayDirection, transRayDirection, &worldMatrixInv); + if (!gore.useTheta) + { + vec3_t t; + VectorCopy(gore.uaxis, t); + TransformPoint(t, gore.uaxis, &worldMatrixInv); + } + + int lod; + ResetGoreTag(); + const int lodbias = Com_Clamp(0, 2, G2_DecideTraceLod(ghoul2[0], r_lodbias->integer)); + const int maxLod = Com_Clamp(0, ghoul2[0].currentModel->numLods, 3); //limit to the number of lods the main model has + + for(lod = lodbias; lod < maxLod; lod++) + { + // now having done that, time to build the model + ri.GetG2VertSpaceServer()->ResetHeap(); + + G2_TransformModel(ghoul2, gore.currentTime, gore.scale, ri.GetG2VertSpaceServer(), lod, true, &gore); + + // now walk each model and compute new texture coordinates + G2_TraceModels(ghoul2, transHitLocation, transRayDirection, 0, gore.entNum, G2_NOCOLLIDE, lod, 1.0f, gore.SSize, gore.TSize, gore.theta, gore.shader, &gore, qtrue); + } +} +#else + +void G2API_ClearSkinGore(CGhoul2Info_v& ghoul2) {} +void G2API_AddSkinGore(CGhoul2Info_v& ghoul2, SSkinGoreData& gore) {} + +#endif + +qboolean G2_TestModelPointers(CGhoul2Info *ghlInfo) // returns true if the model is properly set up +{ + G2ERROR(ghlInfo,"G2_TestModelPointers: NULL ghlInfo"); + if (!ghlInfo) + { + return qfalse; + } + ghlInfo->mValid=false; + if (ghlInfo->mModelindex != -1) + { + ghlInfo->mModel = RE_RegisterModel(ghlInfo->mFileName); + ghlInfo->currentModel = R_GetModelByHandle(ghlInfo->mModel); + if (ghlInfo->currentModel && + ghlInfo->currentModel->type == MOD_MDXM) //Rend2 - data is a union now, so we need to make sure it's also a glm that is loaded + { + if (ghlInfo->currentModel->data.glm && + ghlInfo->currentModel->data.glm->header) + { + mdxmHeader_t *mdxm = ghlInfo->currentModel->data.glm->header; + if (ghlInfo->currentModelSize) + { + if (ghlInfo->currentModelSize != mdxm->ofsEnd) + { + Com_Error(ERR_DROP, "Ghoul2 model was reloaded and has changed, map must be restarted.\n"); + } + } + + ghlInfo->currentModelSize = mdxm->ofsEnd; + ghlInfo->animModel = R_GetModelByHandle(mdxm->animIndex + ghlInfo->animModelIndexOffset); + + if (ghlInfo->animModel) + { + ghlInfo->aHeader = ghlInfo->animModel->data.gla; + if (ghlInfo->aHeader) + { + if (ghlInfo->currentAnimModelSize) + { + if (ghlInfo->currentAnimModelSize!=ghlInfo->aHeader->ofsEnd) + { + Com_Error(ERR_DROP, "Ghoul2 model was reloaded and has changed, map must be restarted.\n"); + } + } + ghlInfo->currentAnimModelSize=ghlInfo->aHeader->ofsEnd; + ghlInfo->mValid=true; + } + } + } + } + } + if (!ghlInfo->mValid) + { + ghlInfo->currentModel = NULL; + ghlInfo->currentModelSize = 0; + ghlInfo->animModel = NULL; + ghlInfo->currentAnimModelSize = 0; + ghlInfo->aHeader = NULL; + } + return (qboolean)ghlInfo->mValid; +} + +#ifdef G2_PERFORMANCE_ANALYSIS +#include "qcommon/timing.h" +extern timing_c G2PerformanceTimer_G2_SetupModelPointers; +extern int G2Time_G2_SetupModelPointers; +#endif + +qboolean G2_SetupModelPointers(CGhoul2Info *ghlInfo) // returns true if the model is properly set up +{ +#ifdef G2_PERFORMANCE_ANALYSIS + G2PerformanceTimer_G2_SetupModelPointers.Start(); +#endif + G2ERROR(ghlInfo,"G2_SetupModelPointers: NULL ghlInfo"); + if (!ghlInfo) + { + return qfalse; + } + + ghlInfo->mValid=false; + + if (ghlInfo->mModelindex != -1) + { + G2ERROR(ghlInfo->mFileName[0],"empty ghlInfo->mFileName"); + + // RJ - experimental optimization! + ghlInfo->mModel = RE_RegisterModel(ghlInfo->mFileName); + ghlInfo->currentModel = R_GetModelByHandle(ghlInfo->mModel); + + G2ERROR(ghlInfo->currentModel,va("NULL Model (glm) %s",ghlInfo->mFileName)); + if (ghlInfo->currentModel) + { + G2ERROR(ghlInfo->currentModel->modelData, va("Model has no mdxm (glm) %s", ghlInfo->mFileName)); + + if (ghlInfo->currentModel->data.glm && ghlInfo->currentModel->data.glm->header) + { + mdxmHeader_t *mdxm = ghlInfo->currentModel->data.glm->header; + if (ghlInfo->currentModelSize) + { + if (ghlInfo->currentModelSize!=mdxm->ofsEnd) + { + Com_Error(ERR_DROP, "Ghoul2 model was reloaded and has changed, map must be restarted.\n"); + } + } + ghlInfo->currentModelSize=mdxm->ofsEnd; + G2ERROR(ghlInfo->currentModelSize, va("Zero sized Model? (glm) %s",ghlInfo->mFileName)); + + ghlInfo->animModel = R_GetModelByHandle(mdxm->animIndex + ghlInfo->animModelIndexOffset); + G2ERROR(ghlInfo->animModel, va("NULL Model (gla) %s",ghlInfo->mFileName)); + + if (ghlInfo->animModel) + { + ghlInfo->aHeader = ghlInfo->animModel->data.gla; + G2ERROR(ghlInfo->aHeader,va("Model has no mdxa (gla) %s",ghlInfo->mFileName)); + if (ghlInfo->aHeader) + { + if (ghlInfo->currentAnimModelSize) + { + if (ghlInfo->currentAnimModelSize!=ghlInfo->aHeader->ofsEnd) + { + Com_Error(ERR_DROP, "Ghoul2 model was reloaded and has changed, map must be restarted.\n"); + } + } + + ghlInfo->currentAnimModelSize = ghlInfo->aHeader->ofsEnd; + G2ERROR(ghlInfo->currentAnimModelSize, va("Zero sized Model? (gla) %s",ghlInfo->mFileName)); + ghlInfo->mValid = true; + } + } + } + } + } + if (!ghlInfo->mValid) + { + ghlInfo->currentModel = NULL; + ghlInfo->currentModelSize = 0; + ghlInfo->animModel = NULL; + ghlInfo->currentAnimModelSize = 0; + ghlInfo->aHeader = NULL; + } + +#ifdef G2_PERFORMANCE_ANALYSIS + G2Time_G2_SetupModelPointers += G2PerformanceTimer_G2_SetupModelPointers.End(); +#endif + return (qboolean)ghlInfo->mValid; +} + +qboolean G2_SetupModelPointers(CGhoul2Info_v &ghoul2) // returns true if any model is properly set up +{ + qboolean ret = qfalse; + + for (int i=0; imValid&&(g)->aHeader&&(g)->currentModel&&(g)->animModel) + +//===================================================================================================================== +// Bolt List handling routines - so entities can attach themselves to any part of the model in question + +// Given a bone number, see if that bone is already in our bone list +int G2_Find_Bolt_Bone_Num(boltInfo_v &bltlist, const int boneNum) +{ + if (boneNum == -1) + { + return -1; + } + + // look through entire list + for(size_t i=0; imValid); + boltInfo_t tempBolt; + + assert(surfNum >= 0 && surfNum < (int)slist.size()); + // first up, make sure have a surface first + if (surfNum >= (int)slist.size()) + { + return -1; + } + + // look through entire list - see if it's already there first + for(size_t i=0; imValid); + model_t* mod_m = (model_t*)ghlInfo->currentModel; + model_t* mod_a = (model_t*)ghlInfo->animModel; + int x, surfNum = -1; + mdxaSkel_t* skel; + mdxaSkelOffsets_t* offsets; + boltInfo_t tempBolt; + uint32_t flags; + + // first up, we'll search for that which this bolt names in all the surfaces + surfNum = G2_IsSurfaceLegal(mod_m, boneName, &flags); + + // did we find it as a surface? + if (surfNum != -1) + { + // look through entire list - see if it's already there first + for(size_t i=0; idata.gla; + offsets = (mdxaSkelOffsets_t *)((byte *)mdxa + sizeof(mdxaHeader_t)); + + // walk the entire list of bones in the gla file for this model and see if any match the name of the bone we want to find + for (x=0; x< mdxa->numBones; x++) + { + skel = (mdxaSkel_t *)((byte *)mdxa + sizeof(mdxaHeader_t) + offsets->offsets[x]); + // if name is the same, we found it + if (!Q_stricmp(skel->name, boneName)) + { + break; + } + } + + // check to see we did actually make a match with a bone in the model + if (x == mdxa->numBones) + { + // didn't find it? Error + //assert(0&&x == mod_a->mdxa->numBones); +#ifdef _DEBUG +// Com_Printf("WARNING: %s not found on skeleton\n", boneName); +#endif + return -1; + } + + // look through entire list - see if it's already there first + for(size_t i=0; i- 1; i--) + { + if ((bltlist[i].surfaceNumber == -1) && (bltlist[i].boneNumber == -1)) + { + newSize = i; + } + // once we hit one that isn't a -1, we are done. + else + { + break; + } + } + // do we need to resize? + if (newSize != bltlist.size()) + { + // yes, so lets do it + bltlist.resize(newSize); + } + + } + return qtrue; + } + + assert(0); + + // no + return qfalse; +} + +// set the bolt list to all unused so the bone transformation routine ignores it. +void G2_Init_Bolt_List(boltInfo_v &bltlist) +{ + bltlist.clear(); +} + +// remove any bolts that reference original surfaces, generated surfaces, or bones that aren't active anymore +void G2_RemoveRedundantBolts(boltInfo_v &bltlist, surfaceInfo_v &slist, int *activeSurfaces, int *activeBones) +{ + // walk the bolt list + for (size_t i=0; i +#include "ghoul2/ghoul2_gore.h" +//rww - RAGDOLL_END + +extern mdxaBone_t worldMatrix; +extern mdxaBone_t worldMatrixInv; + +////////////////////////////////// + +//rww - RAGDOLL_BEGIN +#ifndef __linux__ + #include +#else + #include +#endif + +#include "client/client.h" //while this is all "shared" code, there are some places where we want to make cgame callbacks (for ragdoll) only if the cgvm exists +//rww - RAGDOLL_END + +#define RAG_PCJ (0x00001) +#define RAG_PCJ_POST_MULT (0x00002) // has the pcj flag as well +#define RAG_PCJ_MODEL_ROOT (0x00004) // has the pcj flag as well +#define RAG_PCJ_PELVIS (0x00008) // has the pcj flag and POST_MULT as well +#define RAG_EFFECTOR (0x00100) +#define RAG_WAS_NOT_RENDERED (0x01000) // not particularily reliable, more of a hint +#define RAG_WAS_EVER_RENDERED (0x02000) // not particularily reliable, more of a hint +#define RAG_BONE_LIGHTWEIGHT (0x04000) //used to indicate a bone's velocity treatment +#define RAG_PCJ_IK_CONTROLLED (0x08000) //controlled from IK move input +#define RAG_UNSNAPPABLE (0x10000) //cannot be broken out of constraints ever + +// thiese flags are on the model and correspond to... +//#define GHOUL2_RESERVED_FOR_RAGDOLL 0x0ff0 // these are not defined here for dependecies sake +#define GHOUL2_RAG_STARTED 0x0010 // we are actually a ragdoll +#define GHOUL2_RAG_PENDING 0x0100 // got start death anim but not end death anim +#define GHOUL2_RAG_DONE 0x0200 // got end death anim +#define GHOUL2_RAG_COLLISION_DURING_DEATH 0x0400 // ever have gotten a collision (da) event +#define GHOUL2_RAG_COLLISION_SLIDE 0x0800 // ever have gotten a collision (slide) event +#define GHOUL2_RAG_FORCESOLVE 0x1000 //api-override, determine if ragdoll should be forced to continue solving even if it thinks it is settled + +// functions predefinition +static void G2_DoIK(CGhoul2Info_v& ghoul2V, int g2Index, CRagDollUpdateParams* params); +static void G2_RagDoll(CGhoul2Info_v& ghoul2V, int g2Index, CRagDollUpdateParams* params, int curTime); + +//===================================================================================================================== +// Bone List handling routines - so entities can override bone info on a bone by bone level, and also interrogate this info + +// Given a bone name, see if that bone is already in our bone list - note the model_t pointer that gets passed in here MUST point at the +// gla file, not the glm file type. +int G2_Find_Bone(CGhoul2Info* ghlInfo, boneInfo_v& blist, const char* boneName) +{ + mdxaSkel_t* skel; + mdxaSkelOffsets_t* offsets; + offsets = (mdxaSkelOffsets_t*)((byte*)ghlInfo->aHeader + sizeof(mdxaHeader_t)); + skel = (mdxaSkel_t*)((byte*)ghlInfo->aHeader + sizeof(mdxaHeader_t) + offsets->offsets[0]); + + // look through entire list + for (size_t i = 0; i < blist.size(); i++) + { + // if this bone entry has no info in it, bounce over it + if (blist[i].boneNumber == -1) + { + continue; + } + + // figure out what skeletal info structure this bone entry is looking at + skel = (mdxaSkel_t*)((byte*)ghlInfo->aHeader + sizeof(mdxaHeader_t) + offsets->offsets[blist[i].boneNumber]); + + // if name is the same, we found it + if (!Q_stricmp(skel->name, boneName)) + { + return i; + } + } + + // didn't find it + return -1; +} + +// Given a bone name, see if that bone is already in our bone list - note the model_t pointer that gets passed in here MUST point at the +// gla file, not the glm file type. +int G2_Find_Bone(const model_t *mod, boneInfo_v &blist, const char *boneName) +{ + mdxaSkel_t *skel; + mdxaSkelOffsets_t *offsets; + mdxaHeader_t *mdxa = mod->data.gla; + offsets = (mdxaSkelOffsets_t *)((byte *)mdxa + sizeof(mdxaHeader_t)); + skel = (mdxaSkel_t *)((byte *)mdxa + sizeof(mdxaHeader_t) + offsets->offsets[0]); + + // look through entire list + for(size_t i=0; ioffsets[blist[i].boneNumber]); + + // if name is the same, we found it + if (!Q_stricmp(skel->name, boneName)) + { + return i; + } + } + + // didn't find it + return -1; +} + +// we need to add a bone to the list - find a free one and see if we can find a corresponding bone in the gla file +int G2_Add_Bone (const model_t *mod, boneInfo_v &blist, const char *boneName) +{ + int x; + mdxaSkel_t *skel; + mdxaSkelOffsets_t *offsets; + boneInfo_t tempBone; + mdxaHeader_t *mdxa = mod->data.gla; + + //rww - RAGDOLL_BEGIN + memset(&tempBone, 0, sizeof(tempBone)); + //rww - RAGDOLL_END + + offsets = (mdxaSkelOffsets_t *)((byte *)mdxa + sizeof(mdxaHeader_t)); + + // walk the entire list of bones in the gla file for this model and see if any match the name of the bone we want to find + for (x=0; x< mdxa->numBones; x++) + { + skel = (mdxaSkel_t *)((byte *)mdxa + sizeof(mdxaHeader_t) + offsets->offsets[x]); + // if name is the same, we found it + if (!Q_stricmp(skel->name, boneName)) + { + break; + } + } + + // check to see we did actually make a match with a bone in the model + if (x == mdxa->numBones) + { + // didn't find it? Error + //assert(0); +#ifdef _DEBUG + Com_Printf("WARNING: Failed to add bone %s\n", boneName); +#endif + +#ifdef _RAG_PRINT_TEST + Com_Printf("WARNING: Failed to add bone %s\n", boneName); +#endif + return -1; + } + + // look through entire list - see if it's already there first + for(size_t i=0; ioffsets[blist[i].boneNumber]); + // if name is the same, we found it + if (!Q_stricmp(skel->name, boneName)) + { + return i; + } + } + else + { + // if we found an entry that had a -1 for the bonenumber, then we hit a bone slot that was empty + blist[i].boneNumber = x; + blist[i].flags = 0; + return i; + } + } + +#ifdef _RAG_PRINT_TEST + Com_Printf("New bone added for %s\n", boneName); +#endif + // ok, we didn't find an existing bone of that name, or an empty slot. Lets add an entry + tempBone.boneNumber = x; + tempBone.flags = 0; + blist.push_back(tempBone); + return blist.size()-1; +} + + +// Given a model handle, and a bone name, we want to remove this bone from the bone override list +qboolean G2_Remove_Bone_Index ( boneInfo_v &blist, int index) +{ + /* + if (index != -1) + { + if (blist[index].flags & BONE_ANGLES_RAGDOLL) + { + return qtrue; // don't accept any calls on ragdoll bones + } + } + */ + + // did we find it? + if (index != -1) + { + // check the flags first - if it's still being used Do NOT remove it + if (!blist[index].flags) + { + + // set this bone to not used + blist[index].boneNumber = -1; + + unsigned int newSize = blist.size(); + // now look through the list from the back and see if there is a block of -1's we can resize off the end of the list + for (int i=blist.size()-1; i>-1; i--) + { + if (blist[i].boneNumber == -1) + { + newSize = i; + } + // once we hit one that isn't a -1, we are done. + else + { + break; + } + } + // do we need to resize? + if (newSize != blist.size()) + { + // yes, so lets do it + blist.resize(newSize); + } + + return qtrue; + } + } + +// assert(0); + // no + return qfalse; +} + +// given a bone number, see if there is an override bone in the bone list +int G2_Find_Bone_In_List(boneInfo_v &blist, const int boneNum) +{ + // look through entire list + for(size_t i=0; idata.gla; + offsets = (mdxaSkelOffsets_t *)((byte *)mdxa + sizeof(mdxaHeader_t)); + skel = (mdxaSkel_t *)((byte *)mdxa + sizeof(mdxaHeader_t) + offsets->offsets[blist[index].boneNumber]); + + Mat3x4_Multiply(&temp1, boneOverride,&skel->BasePoseMatInv); + Mat3x4_Multiply(boneOverride,&skel->BasePoseMat, &temp1); + + } + else + { + VectorCopy(angles, newAngles); + + // why I should need do this Fuck alone knows. But I do. + if (left == POSITIVE_Y) + { + newAngles[0] +=180; + } + + Create_Matrix(newAngles, &temp1); + + permutation.matrix[0][0] = permutation.matrix[0][1] = permutation.matrix[0][2] = permutation.matrix[0][3] = 0; + permutation.matrix[1][0] = permutation.matrix[1][1] = permutation.matrix[1][2] = permutation.matrix[1][3] = 0; + permutation.matrix[2][0] = permutation.matrix[2][1] = permutation.matrix[2][2] = permutation.matrix[2][3] = 0; + + // determine what axis newAngles Yaw should revolve around + switch (forward) + { + case NEGATIVE_X: + permutation.matrix[0][0] = -1; // works + break; + case POSITIVE_X: + permutation.matrix[0][0] = 1; // works + break; + case NEGATIVE_Y: + permutation.matrix[1][0] = -1; + break; + case POSITIVE_Y: + permutation.matrix[1][0] = 1; + break; + case NEGATIVE_Z: + permutation.matrix[2][0] = -1; + break; + case POSITIVE_Z: + permutation.matrix[2][0] = 1; + break; + default: + break; + } + + // determine what axis newAngles pitch should revolve around + switch (left) + { + case NEGATIVE_X: + permutation.matrix[0][1] = -1; + break; + case POSITIVE_X: + permutation.matrix[0][1] = 1; + break; + case NEGATIVE_Y: + permutation.matrix[1][1] = -1; // works + break; + case POSITIVE_Y: + permutation.matrix[1][1] = 1; // works + break; + case NEGATIVE_Z: + permutation.matrix[2][1] = -1; + break; + case POSITIVE_Z: + permutation.matrix[2][1] = 1; + break; + default: + break; + } + + // determine what axis newAngles Roll should revolve around + switch (up) + { + case NEGATIVE_X: + permutation.matrix[0][2] = -1; + break; + case POSITIVE_X: + permutation.matrix[0][2] = 1; + break; + case NEGATIVE_Y: + permutation.matrix[1][2] = -1; + break; + case POSITIVE_Y: + permutation.matrix[1][2] = 1; + break; + case NEGATIVE_Z: + permutation.matrix[2][2] = -1; // works + break; + case POSITIVE_Z: + permutation.matrix[2][2] = 1; // works + break; + default: + break; + } + + Mat3x4_Multiply(boneOverride, &temp1,&permutation); + + } + + // keep a copy of the matrix in the newmatrix which is actually what we use + memcpy(&blist[index].newMatrix, &blist[index].matrix, sizeof(mdxaBone_t)); + +} + +//========================================================================================= +//// Public Bone Routines + + +// Given a model handle, and a bone name, we want to remove this bone from the bone override list +qboolean G2_Remove_Bone (CGhoul2Info *ghlInfo, boneInfo_v &blist, const char *boneName) +{ + assert(ghlInfo->animModel); + int index = G2_Find_Bone(ghlInfo->animModel, blist, boneName); + if (index == -1) + { + return qfalse; + } + + return G2_Remove_Bone_Index(blist, index); +} + +#define DEBUG_PCJ (0) + + +// Given a model handle, and a bone name, we want to set angles specifically +// for overriding +qboolean G2_Set_Bone_Angles_Index(CGhoul2Info* ghlInfo, boneInfo_v& blist, const int index, + const float* angles, const int flags, const Eorientations yaw, + const Eorientations pitch, const Eorientations roll, + const int blendTime, const int currentTime) +{ + if (index < 0 || (index >= (int)blist.size()) || (blist[index].boneNumber == -1)) + { + return qfalse; + } + + // yes, so set the angles and flags correctly + blist[index].flags &= ~BONE_ANGLES_TOTAL; + blist[index].flags |= flags; + blist[index].boneBlendStart = currentTime; + blist[index].boneBlendTime = blendTime; + +#if DEBUG_PCJ + OutputDebugString(va("%8x %2d %6d (%6.2f,%6.2f,%6.2f) %d %d %d %d\n", (int)ghlInfo, index, currentTime, angles[0], angles[1], angles[2], yaw, pitch, roll, flags)); +#endif + G2_Generate_Matrix(ghlInfo->animModel, blist, index, angles, flags, yaw, pitch, roll); + return qtrue; +} + +// Given a model handle, and a bone name, we want to set angles specifically for overriding +qboolean G2_Set_Bone_Angles(CGhoul2Info *ghlInfo, boneInfo_v &blist, const char *boneName, const float *angles, + const int flags, const Eorientations up, const Eorientations left, const Eorientations forward, + const int blendTime, const int currentTime) +{ + model_t* mod_a = (model_t *)ghlInfo->animModel; + + int index = G2_Find_Bone(mod_a, blist, boneName); + if (index == -1) + { + index = G2_Add_Bone(mod_a, blist, boneName); + } + + // did we find it? + if (index != -1) + { + if (blist[index].flags & BONE_ANGLES_RAGDOLL) + { + return qtrue; // don't accept any calls on ragdoll bones + } + + // yes, so set the angles and flags correctly + blist[index].flags &= ~(BONE_ANGLES_TOTAL); + blist[index].flags |= flags; + blist[index].boneBlendStart = currentTime; + blist[index].boneBlendTime = blendTime; +#if DEBUG_PCJ + Com_OPrintf("%2d %6d (%6.2f,%6.2f,%6.2f) %d %d %d %d\n",index,currentTime,angles[0],angles[1],angles[2],up,left,forward,flags); +#endif + + G2_Generate_Matrix(mod_a, blist, index, angles, flags, up, left, forward); + return qtrue; + } + + // failed to add bone + return qfalse; +} + +// Given a model handle, and a bone name, we want to set angles specifically for overriding - using a matrix directly +qboolean G2_Set_Bone_Angles_Matrix_Index(boneInfo_v& blist, const int index, + const mdxaBone_t& matrix, const int flags, + const int blendTime, const int currentTime) +{ + + if ((index >= (int)blist.size()) || (blist[index].boneNumber == -1)) + { + // we are attempting to set a bone override that doesn't exist + assert(0); + return qfalse; + } + + if (index != -1 && (blist[index].flags & BONE_ANGLES_RAGDOLL)) + { + return qtrue; // don't accept any calls on ragdoll bones + } + // yes, so set the angles and flags correctly + blist[index].flags &= ~(BONE_ANGLES_TOTAL); + blist[index].flags |= flags; + blist[index].boneBlendStart = currentTime; + blist[index].boneBlendTime = blendTime; + + memcpy(&blist[index].matrix, &matrix, sizeof(mdxaBone_t)); + memcpy(&blist[index].newMatrix, &matrix, sizeof(mdxaBone_t)); + return qtrue; + +} + +// Given a model handle, and a bone name, we want to set angles specifically for overriding - using a matrix directly +qboolean G2_Set_Bone_Angles_Matrix(CGhoul2Info* ghlInfo, boneInfo_v& blist, const char* boneName, const mdxaBone_t& matrix, + const int flags, const int blendTime, const int currentTime) +{ + int index = G2_Find_Bone(ghlInfo, blist, boneName); + if (index == -1) + { + index = G2_Add_Bone(ghlInfo->animModel, blist, boneName); + } + + // did we find it? + if (index != -1) + { + // yes, so set the angles and flags correctly + blist[index].flags &= ~(BONE_ANGLES_TOTAL); + blist[index].flags |= flags; + + memcpy(&blist[index].matrix, &matrix, sizeof(mdxaBone_t)); + memcpy(&blist[index].newMatrix, &matrix, sizeof(mdxaBone_t)); + return qtrue; + } + return qfalse; +} + +#define DEBUG_G2_TIMING (0) + +// given a model, bone name, a bonelist, a start/end frame number, a anim speed and some anim flags, set up or modify an existing bone entry for a new set of anims +qboolean G2_Set_Bone_Anim_Index( + boneInfo_v &blist, const int index, const int startFrame, const int endFrame, const int flags, const float animSpeed, + const int currentTime, const float setFrame, const int blendTime, const int numFrames) +{ + int modFlags = flags; + + if ((index >= (int)blist.size()) || (blist[index].boneNumber == -1)) + { + // we are attempting to set a bone override that doesn't exist + assert(0); + return qfalse; + } + + // sanity check to see if setfram is within animation bounds + assert((setFrame == -1) || ((setFrame >= startFrame) && (setFrame < endFrame)) || ((setFrame > endFrame) && (setFrame <= (startFrame + 1)))); + + if (modFlags & BONE_ANIM_BLEND) + { + float currentFrame, animSpeed; + int startFrame, endFrame, flags; + // figure out where we are now + if (G2_Get_Bone_Anim_Index(blist, index, currentTime, ¤tFrame, &startFrame, &endFrame, &flags, &animSpeed, numFrames)) + { + if (blist[index].blendStart == currentTime) //we're replacing a blend in progress which hasn't started + { + // set the amount of time it's going to take to blend this anim with the last frame of the last one + blist[index].blendTime = blendTime; + } + else + { + if (animSpeed<0.0f) + { + blist[index].blendFrame = floor(currentFrame); + blist[index].blendLerpFrame = floor(currentFrame); + } + else + { + blist[index].blendFrame = currentFrame; + blist[index].blendLerpFrame = currentFrame+1; + + // cope with if the lerp frame is actually off the end of the anim + if (blist[index].blendFrame >= endFrame ) + { + // we only want to lerp with the first frame of the anim if we are looping + if (blist[index].flags & BONE_ANIM_OVERRIDE_LOOP) + { + blist[index].blendFrame = startFrame; + } + // if we intend to end this anim or freeze after this, then just keep on the last frame + else + { + // assert(endFrame>0); + if (endFrame <= 0) + { + blist[index].blendLerpFrame = 0; + } + else + { + blist[index].blendFrame = endFrame -1; + } + } + } + + // cope with if the lerp frame is actually off the end of the anim + if (blist[index].blendLerpFrame >= endFrame ) + { + // we only want to lerp with the first frame of the anim if we are looping + if (blist[index].flags & BONE_ANIM_OVERRIDE_LOOP) + { + blist[index].blendLerpFrame = startFrame; + } + // if we intend to end this anim or freeze after this, then just keep on the last frame + else + { + // assert(endFrame>0); + if (endFrame <= 0) + { + blist[index].blendLerpFrame = 0; + } + else + { + blist[index].blendLerpFrame = endFrame - 1; + } + } + } + } + // set the amount of time it's going to take to blend this anim with the last frame of the last one + blist[index].blendTime = blendTime; + blist[index].blendStart = currentTime; + + } + } + // hmm, we weren't animating on this bone. In which case disable the blend + else + { + blist[index].blendFrame = blist[index].blendLerpFrame = 0; + blist[index].blendTime = 0; + modFlags &= ~(BONE_ANIM_BLEND); + } + } + else + { + blist[index].blendFrame = blist[index].blendLerpFrame = 0; + blist[index].blendTime = blist[index].blendStart = 0; + // we aren't blending, so remove the option to do so + modFlags &= ~BONE_ANIM_BLEND; + } + // yes, so set the anim data and flags correctly + blist[index].endFrame = endFrame; + blist[index].startFrame = startFrame; + blist[index].animSpeed = animSpeed; + blist[index].pauseTime = 0; + + assert(blist[index].blendFrame >= 0 && blist[index].blendFrame < numFrames); + assert(blist[index].blendLerpFrame >= 0 && blist[index].blendLerpFrame < numFrames); + // start up the animation:) + if (setFrame != -1) + { + blist[index].startTime = (currentTime - (((setFrame - (float)startFrame) * 50.0) / animSpeed)); + } + else + { + blist[index].startTime = currentTime; + } + blist[index].flags &= ~(BONE_ANIM_TOTAL); + blist[index].flags |= modFlags; + +#if DEBUG_G2_TIMING + if (index==2) + { + const boneInfo_t &bone=blist[index]; + char mess[1000]; + if (bone.flags&BONE_ANIM_BLEND) + { + sprintf(mess,"sab[%2d] %5d %5d (%5d-%5d) %4.2f %4x bt(%5d-%5d) %7.2f %5d\n", + index, + currentTime, + bone.startTime, + bone.startFrame, + bone.endFrame, + bone.animSpeed, + bone.flags, + bone.blendStart, + bone.blendStart+bone.blendTime, + bone.blendFrame, + bone.blendLerpFrame + ); + } + else + { + sprintf(mess,"saa[%2d] %5d %5d (%5d-%5d) %4.2f %4x\n", + index, + currentTime, + bone.startTime, + bone.startFrame, + bone.endFrame, + bone.animSpeed, + bone.flags + ); + } + Com_OPrintf("%s",mess); + } +#endif + + return qtrue; + +} + +// given a model, bone name, a bonelist, a start/end frame number, a anim speed and some anim flags, set up or modify an existing bone entry for a new set of anims +qboolean G2_Set_Bone_Anim(CGhoul2Info *ghlInfo, boneInfo_v &blist, const char *boneName, const int startFrame, const int endFrame, + const int flags, const float animSpeed, const int currentTime, const float setFrame, const int blendTime) +{ + model_t* mod_a = (model_t *)ghlInfo->animModel; + int modFlags = flags; + int index = G2_Find_Bone(mod_a, blist, boneName); + + // did we find it? + if (index != -1) + { + return G2_Set_Bone_Anim_Index(blist, index, startFrame, endFrame, modFlags, animSpeed, currentTime, setFrame, blendTime, ghlInfo->aHeader->numFrames); + } + + // no - lets try and add this bone in + index = G2_Add_Bone(ghlInfo->animModel, blist, boneName); + + // did we find a free one? + if (index != -1) + { + blist[index].blendFrame = blist[index].blendLerpFrame = 0; + blist[index].blendTime = 0; + // we aren't blending, so remove the option to do so + modFlags &= ~BONE_ANIM_BLEND; + // yes, so set the anim data and flags correctly + blist[index].endFrame = endFrame; + blist[index].startFrame = startFrame; + blist[index].animSpeed = animSpeed; + blist[index].pauseTime = 0; + // start up the animation:) + if (setFrame != -1) + { + blist[index].startTime = (currentTime - (((setFrame - (float)startFrame) * 50.0) / animSpeed)); + } + else + { + blist[index].startTime = currentTime; + } + blist[index].flags &= ~BONE_ANIM_TOTAL; + blist[index].flags |= modFlags; + assert(blist[index].blendFrame >= 0 && blist[index].blendFrame < ghlInfo->aHeader->numFrames); + assert(blist[index].blendLerpFrame >= 0 && blist[index].blendLerpFrame < ghlInfo->aHeader->numFrames); + return qtrue; + } + + return qfalse; +} + +qboolean G2_Get_Bone_Anim_Range_Index(boneInfo_v& blist, const int boneIndex, int* startFrame, int* endFrame) +{ + if (boneIndex != -1) + { + assert(boneIndex >= 0 && boneIndex < (int)blist.size()); + // are we an animating bone? + if (blist[boneIndex].flags & (BONE_ANIM_OVERRIDE_LOOP | BONE_ANIM_OVERRIDE)) + { + *startFrame = blist[boneIndex].startFrame; + *endFrame = blist[boneIndex].endFrame; + return qtrue; + } + } + return qfalse; +} + +qboolean G2_Get_Bone_Anim_Range(CGhoul2Info *ghlInfo, boneInfo_v &blist, const char *boneName, int *startFrame, int *endFrame) +{ + model_t *mod_a = (model_t *)ghlInfo->animModel; + int index = G2_Find_Bone(mod_a, blist, boneName); + + // did we find it? + if (index != -1) + { + // are we an animating bone? + if (blist[index].flags & (BONE_ANIM_OVERRIDE_LOOP | BONE_ANIM_OVERRIDE)) + { + *startFrame = blist[index].startFrame; + *endFrame = blist[index].endFrame; + return qtrue; + } + } + return qfalse; +} + +// given a model, bonelist and bonename, return the current frame, startframe and endframe of the current animation +// NOTE if we aren't running an animation, then qfalse is returned +void G2_TimingModel(boneInfo_t &bone,int currentTime,int numFramesInFile,int ¤tFrame,int &newFrame,float &lerp); + +qboolean G2_Get_Bone_Anim_Index(boneInfo_v& blist, const int index, const int currentTime, + float* currentFrame, int* startFrame, int* endFrame, int* flags, float* retAnimSpeed, int numFrames) +{ + + // did we find it? + if ((index>=0) && !((index >= (int)blist.size()) || (blist[index].boneNumber == -1))) + { + + // are we an animating bone? + if (blist[index].flags & (BONE_ANIM_OVERRIDE_LOOP | BONE_ANIM_OVERRIDE)) + { + int lcurrentFrame,newFrame; + float lerp; + G2_TimingModel(blist[index],currentTime,numFrames,lcurrentFrame,newFrame,lerp); + + if (currentFrame) *currentFrame =float(lcurrentFrame)+lerp; + if (startFrame) *startFrame = blist[index].startFrame; + if (endFrame) *endFrame = blist[index].endFrame; + if (flags) *flags = blist[index].flags; + if (retAnimSpeed) *retAnimSpeed = blist[index].animSpeed; + return qtrue; + } + } + + if (startFrame) *startFrame=0; + if (endFrame) *endFrame=1; + if (currentFrame) *currentFrame=0.0f; + if (flags) *flags=0; + if (retAnimSpeed) *retAnimSpeed=0.0f; + return qfalse; +} + +// given a model, bonelist and bonename, return the current frame, startframe and endframe of the current animation +// NOTE if we aren't running an animation, then qfalse is returned +qboolean G2_Get_Bone_Anim(CGhoul2Info* ghlInfo, boneInfo_v& blist, const char* boneName, const int currentTime, + float* currentFrame, int* startFrame, int* endFrame, int* flags, float* retAnimSpeed) +{ + model_t* mod_a = (model_t *)ghlInfo->animModel; + int index = G2_Find_Bone(mod_a, blist, boneName); + + if (index==-1) + { + index = G2_Add_Bone(mod_a, blist, boneName); + + if (index == -1) + { + return qfalse; + } + } + + assert(ghlInfo->aHeader); + + if (G2_Get_Bone_Anim_Index(blist, index, currentTime, currentFrame, startFrame, endFrame, flags, retAnimSpeed, ghlInfo->aHeader->numFrames)) + { + assert(*startFrame>=0&&*startFrameaHeader->numFrames); + assert(*endFrame>0&&*endFrame<=ghlInfo->aHeader->numFrames); + assert(*currentFrame>=0.0f&&((int)(*currentFrame))aHeader->numFrames); + return qtrue; + } + + return qfalse; +} + +// given a model, bonelist and bonename, lets pause an anim if it's playing. +qboolean G2_Pause_Bone_Anim_Index(boneInfo_v& blist, const int boneIndex, const int currentTime, int numFrames) +{ + if (boneIndex >= 0 && boneIndex < (int)blist.size()) + { + // are we pausing or un pausing? + if (blist[boneIndex].pauseTime) + { + int startFrame, endFrame, flags; + float currentFrame, animSpeed; + + // figure out what frame we are on now + if (G2_Get_Bone_Anim_Index(blist, boneIndex, blist[boneIndex].pauseTime, ¤tFrame, &startFrame, &endFrame, &flags, &animSpeed, numFrames)) + { + // reset start time so we are actually on this frame right now + G2_Set_Bone_Anim_Index(blist, boneIndex, startFrame, endFrame, flags, animSpeed, currentTime, currentFrame, 0, numFrames); + // no pausing anymore + blist[boneIndex].pauseTime = 0; + } + else + { + return qfalse; + } + } + // ahh, just pausing, the easy bit + else + { + blist[boneIndex].pauseTime = currentTime; + } + + return qtrue; + } + assert(0); + + return qfalse; +} + +// given a model, bonelist and bonename, lets pause an anim if it's playing. +qboolean G2_Pause_Bone_Anim(CGhoul2Info *ghlInfo, boneInfo_v &blist, const char *boneName, const int currentTime) +{ + model_t* mod_a = (model_t *)ghlInfo->animModel; + int index = G2_Find_Bone(mod_a, blist, boneName); + + // did we find it? + if (index != -1) + { + return (G2_Pause_Bone_Anim_Index(blist, index, currentTime, ghlInfo->aHeader->numFrames)); + } + return qfalse; +} + +qboolean G2_IsPaused(CGhoul2Info* ghlInfo, boneInfo_v& blist, const char* boneName) +{ + int index = G2_Find_Bone(ghlInfo, blist, boneName); + if (index != -1) + { + // are we paused? + if (blist[index].pauseTime) + { + // yup. paused. + return qtrue; + } + return qfalse; + } + + return qfalse; +} + +// given a model, bonelist and bonename, lets stop an anim if it's playing. +qboolean G2_Stop_Bone_Anim_Index(boneInfo_v &blist, const int index) +{ + + if ((index >= (int)blist.size()) || (blist[index].boneNumber == -1)) + { + // we are attempting to set a bone override that doesn't exist + return qfalse; + } + + blist[index].flags &= ~(BONE_ANIM_TOTAL); + // try and remove this bone if we can + return G2_Remove_Bone_Index(blist, index); +} + +// given a model, bonelist and bonename, lets stop an anim if it's playing. +qboolean G2_Stop_Bone_Anim(CGhoul2Info* ghlInfo, boneInfo_v& blist, const char* boneName) +{ + int index = G2_Find_Bone(ghlInfo, blist, boneName); + + // did we find it? + if (index != -1) + { + blist[index].flags &= ~(BONE_ANIM_TOTAL); + // try and remove this bone if we can + return G2_Remove_Bone_Index(blist, index); + } + assert(0); + + return qfalse; +} + +// given a model, bonelist and bonename, lets stop an anim if it's playing. +qboolean G2_Stop_Bone_Angles_Index(boneInfo_v &blist, const int index) +{ + + if ((index >= (int)blist.size()) || (blist[index].boneNumber == -1)) + { + // we are attempting to set a bone override that doesn't exist + assert(0); + return qfalse; + } + + blist[index].flags &= ~(BONE_ANGLES_TOTAL); + // try and remove this bone if we can + return G2_Remove_Bone_Index(blist, index); + +} + +// given a model, bonelist and bonename, lets stop an anim if it's playing. +qboolean G2_Stop_Bone_Angles(CGhoul2Info* ghlInfo, boneInfo_v& blist, const char* boneName) +{ + int index = G2_Find_Bone(ghlInfo, blist, boneName); + + // did we find it? + if (index != -1) + { + blist[index].flags &= ~(BONE_ANGLES_TOTAL); + // try and remove this bone if we can + return G2_Remove_Bone_Index(blist, index); + } + assert(0); + + return qfalse; +} + + +// actually walk the bone list and update each and every bone if we have ended an animation for them. + +void G2_Animate_Bone_List(CGhoul2Info_v &ghoul2, const int currentTime, const int index, CRagDollUpdateParams* params) +{ + bool anyRagDoll = false; + bool anyIK = false; + for (size_t i = 0; i < ghoul2[index].mBlist.size(); i++) + { + if (ghoul2[index].mBlist[i].boneNumber != -1) + { + if (ghoul2[index].mBlist[i].flags & BONE_ANGLES_RAGDOLL) + { + if (ghoul2[index].mBlist[i].RagFlags & RAG_PCJ_IK_CONTROLLED) + { + anyIK = true; + } + anyRagDoll = true; + + if (anyIK && anyRagDoll) + { + break; + } + } + } + } + if (!index && params) + { + if (anyIK) + { + //we use ragdoll params so we know what our current position, etc. is. + G2_DoIK(ghoul2, 0, params); + } + else + { + G2_RagDoll(ghoul2, 0, params, currentTime); + } + } +} + +//rww - RAGDOLL_BEGIN +/* + + + rag stuff + +*/ +static void G2_RagDollSolve(CGhoul2Info_v &ghoul2V,int g2Index,float decay,int frameNum,const vec3_t currentOrg,bool LimitAngles,CRagDollUpdateParams *params = NULL); +static void G2_RagDollCurrentPosition(CGhoul2Info_v &ghoul2V,int g2Index,int frameNum,const vec3_t angles,const vec3_t position,const vec3_t scale); +static bool G2_RagDollSettlePositionNumeroTrois(CGhoul2Info_v &ghoul2V,const vec3_t currentOrg,CRagDollUpdateParams *params, int curTime); +static bool G2_RagDollSetup(CGhoul2Info &ghoul2,int frameNum,bool resetOrigin,const vec3_t origin,bool anyRendered); + +void G2_GetBoneBasepose(CGhoul2Info &ghoul2,int boneNum,mdxaBone_t *&retBasepose,mdxaBone_t *&retBaseposeInv); +int G2_GetBoneDependents(CGhoul2Info &ghoul2,int boneNum,int *tempDependents,int maxDep); +void G2_GetBoneMatrixLow(CGhoul2Info &ghoul2,int boneNum,const vec3_t scale,mdxaBone_t &retMatrix,mdxaBone_t *&retBasepose,mdxaBone_t *&retBaseposeInv); +int G2_GetParentBoneMatrixLow(CGhoul2Info &ghoul2,int boneNum,const vec3_t scale,mdxaBone_t &retMatrix,mdxaBone_t *&retBasepose,mdxaBone_t *&retBaseposeInv); +bool G2_WasBoneRendered(CGhoul2Info &ghoul2,int boneNum); + +#define MAX_BONES_RAG (256) + +struct SRagEffector +{ + vec3_t currentOrigin; + vec3_t desiredDirection; + vec3_t desiredOrigin; + float radius; + float weight; +}; + +#define RAG_MASK (CONTENTS_SOLID|CONTENTS_TERRAIN)//|CONTENTS_SHOTCLIP|CONTENTS_TERRAIN//(/*MASK_SOLID|*/CONTENTS_SOLID|CONTENTS_PLAYERCLIP|CONTENTS_SHOTCLIP|CONTENTS_TERRAIN|CONTENTS_BODY) + +extern cvar_t *broadsword; +extern cvar_t *broadsword_kickbones; +extern cvar_t *broadsword_kickorigin; +extern cvar_t *broadsword_dontstopanim; +extern cvar_t *broadsword_waitforshot; +extern cvar_t *broadsword_playflop; + +extern cvar_t *broadsword_effcorr; + +extern cvar_t *broadsword_ragtobase; + +extern cvar_t *broadsword_dircap; + +extern cvar_t *broadsword_extra1; +extern cvar_t *broadsword_extra2; + +//#define flrand Q_flrand + +static mdxaBone_t* ragBasepose[MAX_BONES_RAG]; +static mdxaBone_t* ragBaseposeInv[MAX_BONES_RAG]; +static mdxaBone_t ragBones[MAX_BONES_RAG]; +static SRagEffector ragEffectors[MAX_BONES_RAG]; +static boneInfo_t *ragBoneData[MAX_BONES_RAG]; +static int tempDependents[MAX_BONES_RAG]; +static int ragBlistIndex[MAX_BONES_RAG]; +static int numRags; +static vec3_t ragBoneMins; +static vec3_t ragBoneMaxs; +static vec3_t ragBoneCM; +static bool haveDesiredPelvisOffset=false; +static vec3_t desiredPelvisOffset; // this is for the root +static float ragOriginChange=0.0f; +static vec3_t ragOriginChangeDir; +//debug +#if 0 +static vec3_t handPos={0,0,0}; +static vec3_t handPos2={0,0,0}; +#endif + +enum ERagState +{ + ERS_DYNAMIC, + ERS_SETTLING, + ERS_SETTLED +}; +static int ragState; + +static std::vector rag; // once we get the dependents precomputed this can be local + + +static void G2_Generate_MatrixRag( + // caution this must not be called before the whole skeleton is "remembered" + boneInfo_v &blist, + int index) +{ + + + boneInfo_t &bone=blist[index];//.sent; + + memcpy(&bone.matrix,&bone.ragOverrideMatrix, sizeof(mdxaBone_t)); +#ifdef _DEBUG + int i,j; + for (i = 0; i < 3; i++ ) + { + for (j = 0; j < 4; j++ ) + { + assert( !Q_isnan(bone.matrix.matrix[i][j])); + } + } +#endif// _DEBUG + memcpy(&blist[index].newMatrix,&bone.matrix, sizeof(mdxaBone_t)); +} + +int G2_Find_Bone_Rag(CGhoul2Info *ghlInfo, boneInfo_v &blist, const char *boneName) +{ + mdxaSkel_t *skel; + mdxaSkelOffsets_t *offsets; + + offsets = (mdxaSkelOffsets_t *)((byte *)ghlInfo->aHeader + sizeof(mdxaHeader_t)); + skel = (mdxaSkel_t *)((byte *)ghlInfo->aHeader + sizeof(mdxaHeader_t) + offsets->offsets[0]); + + /* + model_t *currentModel; + model_t *animModel; + mdxaHeader_t *aHeader; + + currentModel = R_GetModelByHandle(RE_RegisterModel(ghlInfo->mFileName)); + assert(currentModel); + animModel = R_GetModelByHandle(currentModel->mdxm->animIndex); + assert(animModel); + aHeader = animModel->mdxa; + assert(aHeader); + + offsets = (mdxaSkelOffsets_t *)((byte *)aHeader + sizeof(mdxaHeader_t)); + skel = (mdxaSkel_t *)((byte *)aHeader + sizeof(mdxaHeader_t) + offsets->offsets[0]); + */ + + // look through entire list + for(size_t i=0; iaHeader + sizeof(mdxaHeader_t) + offsets->offsets[blist[i].boneNumber]); + //skel = (mdxaSkel_t *)((byte *)aHeader + sizeof(mdxaHeader_t) + offsets->offsets[blist[i].boneNumber]); + + // if name is the same, we found it + if (!Q_stricmp(skel->name, boneName)) + { + return i; + } + } +#if _DEBUG +// G2_Bone_Not_Found(boneName,ghlInfo->mFileName); +#endif + // didn't find it + return -1; +} + +static int G2_Set_Bone_Rag(const mdxaHeader_t *mod_a, + boneInfo_v &blist, + const char *boneName, + CGhoul2Info &ghoul2, + const vec3_t scale, + const vec3_t origin) +{ + // do not change the state of the skeleton here + int index = G2_Find_Bone_Rag(&ghoul2, blist, boneName); + + if (index == -1) + { + index = G2_Add_Bone(ghoul2.animModel, blist, boneName); + } + + if (index != -1) + { + boneInfo_t &bone=blist[index]; + VectorCopy(origin,bone.extraVec1); + + G2_GetBoneMatrixLow(ghoul2,bone.boneNumber,scale,bone.originalTrueBoneMatrix,bone.basepose,bone.baseposeInv); +// bone.parentRawBoneIndex=G2_GetParentBoneMatrixLow(ghoul2,bone.boneNumber,scale,bone.parentTrueBoneMatrix,bone.baseposeParent,bone.baseposeInvParent); + assert( !Q_isnan(bone.originalTrueBoneMatrix.matrix[1][1])); + assert( !Q_isnan(bone.originalTrueBoneMatrix.matrix[1][3])); + bone.originalOrigin[0]=bone.originalTrueBoneMatrix.matrix[0][3]; + bone.originalOrigin[1]=bone.originalTrueBoneMatrix.matrix[1][3]; + bone.originalOrigin[2]=bone.originalTrueBoneMatrix.matrix[2][3]; + } + return index; +} + +static int G2_Set_Bone_Angles_Rag( + CGhoul2Info &ghoul2, + const mdxaHeader_t *mod_a, + boneInfo_v &blist, + const char *boneName, + const int flags, + const float radius, + const vec3_t angleMin=0, + const vec3_t angleMax=0, + const int blendTime=500) +{ + int index = G2_Find_Bone_Rag(&ghoul2, blist, boneName); + + if (index == -1) + { + index = G2_Add_Bone(ghoul2.animModel, blist, boneName); + } + if (index != -1) + { + boneInfo_t &bone=blist[index]; + bone.flags &= ~(BONE_ANGLES_TOTAL); + bone.flags |= BONE_ANGLES_RAGDOLL; + if (flags&RAG_PCJ) + { + if (flags&RAG_PCJ_POST_MULT) + { + bone.flags |= BONE_ANGLES_POSTMULT; + } + else if (flags&RAG_PCJ_MODEL_ROOT) + { + bone.flags |= BONE_ANGLES_PREMULT; +// bone.flags |= BONE_ANGLES_POSTMULT; + } + else + { + assert(!"Invalid RAG PCJ\n"); + } + } + bone.ragStartTime=G2API_GetTime(0); + bone.boneBlendStart = bone.ragStartTime; + bone.boneBlendTime = blendTime; + bone.radius=radius; + bone.weight=1.0f; + + //init the others to valid values + bone.epGravFactor = 0; + VectorClear(bone.epVelocity); + bone.solidCount = 0; + bone.physicsSettled = false; + bone.snapped = false; + + bone.parentBoneIndex = -1; + + bone.offsetRotation = 0.0f; + + bone.overGradSpeed = 0.0f; + VectorClear(bone.overGoalSpot); + bone.hasOverGoal = false; + bone.hasAnimFrameMatrix = -1; + +// bone.weight=pow(radius,1.7f); //cubed was too harsh +// bone.weight=radius*radius*radius; + if (angleMin&&angleMax) + { + VectorCopy(angleMin,bone.minAngles); + VectorCopy(angleMax,bone.maxAngles); + } + else + { + VectorCopy(bone.currentAngles,bone.minAngles); // I guess this isn't a rag pcj then + VectorCopy(bone.currentAngles,bone.maxAngles); + } + if (!bone.lastTimeUpdated) + { + static mdxaBone_t id = + { + { + { 1.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f, 0.0f } + } + }; + memcpy(&bone.ragOverrideMatrix,&id, sizeof(mdxaBone_t)); + VectorClear(bone.anglesOffset); + VectorClear(bone.positionOffset); + VectorClear(bone.velocityEffector); // this is actually a velocity now + VectorClear(bone.velocityRoot); // this is actually a velocity now + VectorClear(bone.lastPosition); + VectorClear(bone.lastShotDir); + bone.lastContents=0; + // if this is non-zero, we are in a dynamic state + bone.firstCollisionTime=bone.ragStartTime; + // if this is non-zero, we are in a settling state + bone.restTime=0; + // if they are both zero, we are in a settled state + + bone.firstTime=0; + + bone.RagFlags=flags; + bone.DependentRagIndexMask=0; + + G2_Generate_MatrixRag(blist,index); // set everything to th id + +#if 0 + VectorClear(bone.currentAngles); +// VectorAdd(bone.minAngles,bone.maxAngles,bone.currentAngles); +// VectorScale(bone.currentAngles,0.5f,bone.currentAngles); +#else + { + if ( + (flags&RAG_PCJ_MODEL_ROOT) || + (flags&RAG_PCJ_PELVIS) || + !(flags&RAG_PCJ)) + { + VectorClear(bone.currentAngles); + } + else + { + int k; + for (k=0;k<3;k++) + { + float scalar=flrand(-1.0f,1.0f); + scalar*=flrand(-1.0f,1.0f)*flrand(-1.0f,1.0f); + // this is a heavily central distribution + // center it on .5 (and make it small) + scalar*=0.5f; + scalar+=0.5f; + + bone.currentAngles[k]=(bone.minAngles[k]-bone.maxAngles[k])*scalar+bone.maxAngles[k]; + } + } + } +// VectorClear(bone.currentAngles); +#endif + VectorCopy(bone.currentAngles,bone.lastAngles); + } + } + return index; +} + +class CRagDollParams; +const mdxaHeader_t *G2_GetModA(CGhoul2Info &ghoul2); + + +static void G2_RagDollMatchPosition() +{ + haveDesiredPelvisOffset=false; + int i; + for (i=0;inumBones); +#else //The anims on every bone are messed up too, as are the angles. There's not really any way to get back to a normal state, so just clear the list + //and let them re-set their anims/angles gameside. + int i = 0; + while (i < blist.size()) + { + boneInfo_t &bone = blist[i]; + if (bone.boneNumber != -1 && (bone.flags & BONE_ANGLES_RAGDOLL)) + { + bone.flags &= ~BONE_ANGLES_RAGDOLL; + bone.flags &= ~BONE_ANGLES_IK; + bone.RagFlags = 0; + bone.lastTimeUpdated = 0; + VectorClear(bone.currentAngles); + bone.ragStartTime = 0; + } + i++; + } +#endif + ghoul2.mFlags &= ~(GHOUL2_RAG_PENDING|GHOUL2_RAG_DONE|GHOUL2_RAG_STARTED); +} + +void G2_SetRagDoll(CGhoul2Info_v &ghoul2V,CRagDollParams *parms) +{ + if (parms) + { + parms->CallRagDollBegin = false; + } + if (!broadsword||!broadsword->integer||!parms) + { + return; + } + int model; + for (model = 0; model < ghoul2V.size(); model++) + { + if (ghoul2V[model].mModelindex != -1) + { + break; + } + } + if (model==ghoul2V.size()) + { + return; + } + CGhoul2Info &ghoul2=ghoul2V[model]; + const mdxaHeader_t *mod_a=G2_GetModA(ghoul2); + if (!mod_a) + { + return; + } + int curTime=G2API_GetTime(0); + boneInfo_v &blist = ghoul2.mBlist; + int index = G2_Find_Bone_Rag(&ghoul2, blist, "model_root"); + switch (parms->RagPhase) + { + case CRagDollParams::RP_START_DEATH_ANIM: + ghoul2.mFlags|=GHOUL2_RAG_PENDING; + return; /// not doing anything with this yet + break; + case CRagDollParams::RP_END_DEATH_ANIM: + ghoul2.mFlags|=GHOUL2_RAG_PENDING|GHOUL2_RAG_DONE; + if (broadsword_waitforshot && + broadsword_waitforshot->integer) + { + if (broadsword_waitforshot->integer==2) + { + if (!(ghoul2.mFlags&(GHOUL2_RAG_COLLISION_DURING_DEATH|GHOUL2_RAG_COLLISION_SLIDE))) + { + //nothing was encountered, lets just wait for the first shot + return; // we ain't starting yet + } + } + else + { + return; // we ain't starting yet + } + } + break; + case CRagDollParams::RP_DEATH_COLLISION: + if (parms->collisionType) + { + ghoul2.mFlags|=GHOUL2_RAG_COLLISION_SLIDE; + } + else + { + ghoul2.mFlags|=GHOUL2_RAG_COLLISION_DURING_DEATH; + } + if (broadsword_dontstopanim && broadsword_waitforshot && + (broadsword_dontstopanim->integer || broadsword_waitforshot->integer) + ) + { + if (!(ghoul2.mFlags&GHOUL2_RAG_DONE)) + { + return; // we ain't starting yet + } + } + break; + case CRagDollParams::RP_CORPSE_SHOT: + if (broadsword_kickorigin && + broadsword_kickorigin->integer) + { + if (index>=0&&index<(int)blist.size()) + { + boneInfo_t &bone=blist[index]; + if (bone.boneNumber>=0) + { + if (bone.flags & BONE_ANGLES_RAGDOLL) + { + //rww - Would need ent pointer here. But.. since this is SW, we aren't even having corpse shooting anyway I'd imagine. + /* + float magicFactor14=8.0f; //64.0f; // kick strength + + if (parms->fShotStrength) + { //if there is a shot strength, use it instead + magicFactor14 = parms->fShotStrength; + } + + parms->me->s.pos.trType = TR_GRAVITY; + parms->me->s.pos.trDelta[0] += bone.lastShotDir[0]*magicFactor14; + parms->me->s.pos.trDelta[1] += bone.lastShotDir[1]*magicFactor14; + //parms->me->s.pos.trDelta[2] = fabsf(bone.lastShotDir[2])*magicFactor14; + //rww - The vertical portion of this doesn't seem to work very well + //I am just leaving it whatever it is for now, because my velocity scaling + //only works on x and y and the gravity stuff for NPCs is a bit unpleasent + //trying to change/work with + assert( !Q_isnan(bone.lastShotDir[1])); + */ + } + } + } + } + break; + case CRagDollParams::RP_GET_PELVIS_OFFSET: + if (parms->RagPhase==CRagDollParams::RP_GET_PELVIS_OFFSET) + { + VectorClear(parms->pelvisAnglesOffset); + VectorClear(parms->pelvisPositionOffset); + } + // intentional lack of a break + case CRagDollParams::RP_SET_PELVIS_OFFSET: + if (index>=0&&index<(int)blist.size()) + { + boneInfo_t &bone=blist[index]; + if (bone.boneNumber>=0) + { + if (bone.flags & BONE_ANGLES_RAGDOLL) + { + if (parms->RagPhase==CRagDollParams::RP_GET_PELVIS_OFFSET) + { + VectorCopy(bone.anglesOffset,parms->pelvisAnglesOffset); + VectorCopy(bone.positionOffset,parms->pelvisPositionOffset); + } + else + { + VectorCopy(parms->pelvisAnglesOffset,bone.anglesOffset); + VectorCopy(parms->pelvisPositionOffset,bone.positionOffset); + } + } + } + } + return; + break; + case CRagDollParams::RP_DISABLE_EFFECTORS: + // not doing anything with this yet + return; + break; + default: + assert(0); + return; + break; + } + if (ghoul2.mFlags&GHOUL2_RAG_STARTED) + { + // only going to begin ragdoll once, everything else depends on what happens to the origin + return; + } + + ghoul2.mFlags|=GHOUL2_RAG_PENDING|GHOUL2_RAG_DONE|GHOUL2_RAG_STARTED; // well anyway we are going live + parms->CallRagDollBegin=qtrue; + + G2_GenerateWorldMatrix(parms->angles, parms->position); + G2_ConstructGhoulSkeleton(ghoul2V, curTime, false, parms->scale); + + G2_Set_Bone_Rag(mod_a,blist,"model_root",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"pelvis",ghoul2,parms->scale,parms->position); + + G2_Set_Bone_Rag(mod_a,blist,"lower_lumbar",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"upper_lumbar",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"thoracic",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"cranium",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"rhumerus",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"lhumerus",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"rradius",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"lradius",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"rfemurYZ",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"lfemurYZ",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"rtibia",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"ltibia",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"rhand",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"lhand",ghoul2,parms->scale,parms->position); + //G2_Set_Bone_Rag(mod_a,blist,"rtarsal",ghoul2,parms->scale,parms->position); + //G2_Set_Bone_Rag(mod_a,blist,"ltarsal",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"rtalus",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"ltalus",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"rradiusX",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"lradiusX",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"rfemurX",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"lfemurX",ghoul2,parms->scale,parms->position); + G2_Set_Bone_Rag(mod_a,blist,"ceyebrow",ghoul2,parms->scale,parms->position); + + //int startFrame = 3665, endFrame = 3665+1; + int startFrame = parms->startFrame, endFrame = parms->endFrame; + assert(startFrame < mod_a->numFrames); + assert(endFrame < mod_a->numFrames); + + G2_Set_Bone_Anim_No_BS(ghoul2, mod_a,blist,"upper_lumbar",startFrame,endFrame-1, + BONE_ANIM_OVERRIDE_FREEZE|BONE_ANIM_BLEND, + 1.0f,curTime,float(startFrame),150,0,true); + G2_Set_Bone_Anim_No_BS(ghoul2, mod_a,blist,"lower_lumbar",startFrame,endFrame-1, + BONE_ANIM_OVERRIDE_FREEZE|BONE_ANIM_BLEND, + 1.0f,curTime,float(startFrame),150,0,true); + G2_Set_Bone_Anim_No_BS(ghoul2, mod_a,blist,"Motion",startFrame,endFrame-1, + BONE_ANIM_OVERRIDE_FREEZE|BONE_ANIM_BLEND, + 1.0f,curTime,float(startFrame),150,0,true); +// G2_Set_Bone_Anim_No_BS(ghoul2, mod_a,blist,"model_root",startFrame,endFrame-1, +// BONE_ANIM_OVERRIDE_FREEZE|BONE_ANIM_BLEND, +// 1.0f,curTime,float(startFrame),150,0,true); + G2_Set_Bone_Anim_No_BS(ghoul2, mod_a,blist,"lfemurYZ",startFrame,endFrame-1, + BONE_ANIM_OVERRIDE_FREEZE|BONE_ANIM_BLEND, + 1.0f,curTime,float(startFrame),150,0,true); + G2_Set_Bone_Anim_No_BS(ghoul2, mod_a,blist,"rfemurYZ",startFrame,endFrame-1, + BONE_ANIM_OVERRIDE_FREEZE|BONE_ANIM_BLEND, + 1.0f,curTime,float(startFrame),150,0,true); + + G2_Set_Bone_Anim_No_BS(ghoul2, mod_a,blist,"rhumerus",startFrame,endFrame-1, + BONE_ANIM_OVERRIDE_FREEZE|BONE_ANIM_BLEND, + 1.0f,curTime,float(startFrame),150,0,true); + G2_Set_Bone_Anim_No_BS(ghoul2, mod_a,blist,"lhumerus",startFrame,endFrame-1, + BONE_ANIM_OVERRIDE_FREEZE|BONE_ANIM_BLEND, + 1.0f,curTime,float(startFrame),150,0,true); + + G2_ConstructGhoulSkeleton(ghoul2V, curTime, false, parms->scale); + + static const float fRadScale = 0.3f;//0.5f; + + vec3_t pcjMin,pcjMax; + VectorSet(pcjMin,-90.0f,-45.0f,-45.0f); + VectorSet(pcjMax,90.0f,45.0f,45.0f); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"model_root",RAG_PCJ_MODEL_ROOT|RAG_PCJ|RAG_UNSNAPPABLE,10.0f*fRadScale,pcjMin,pcjMax,100); + VectorSet(pcjMin,-45.0f,-45.0f,-45.0f); + VectorSet(pcjMax,45.0f,45.0f,45.0f); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"pelvis",RAG_PCJ_PELVIS|RAG_PCJ|RAG_PCJ_POST_MULT|RAG_UNSNAPPABLE,10.0f*fRadScale,pcjMin,pcjMax,100); + +#if 1 + // new base anim, unconscious flop + int pcjflags=RAG_PCJ|RAG_PCJ_POST_MULT;//|RAG_EFFECTOR; + + VectorSet(pcjMin,-15.0f,-15.0f,-15.0f); + VectorSet(pcjMax,15.0f,15.0f,15.0f); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"lower_lumbar",pcjflags|RAG_UNSNAPPABLE,10.0f*fRadScale,pcjMin,pcjMax,500); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"upper_lumbar",pcjflags|RAG_UNSNAPPABLE,10.0f*fRadScale,pcjMin,pcjMax,500); + VectorSet(pcjMin,-25.0f,-25.0f,-25.0f); + VectorSet(pcjMax,25.0f,25.0f,25.0f); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"thoracic",pcjflags|RAG_EFFECTOR|RAG_UNSNAPPABLE,12.0f*fRadScale,pcjMin,pcjMax,500); + + VectorSet(pcjMin,-10.0f,-10.0f,-90.0f); + VectorSet(pcjMax,10.0f,10.0f,90.0f); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"cranium",pcjflags|RAG_BONE_LIGHTWEIGHT|RAG_UNSNAPPABLE,6.0f*fRadScale,pcjMin,pcjMax,500); + + static const float sFactLeg = 1.0f; + static const float sFactArm = 1.0f; + static const float sRadArm = 1.0f; + static const float sRadLeg = 1.0f; + + VectorSet(pcjMin,-100.0f,-40.0f,-15.0f); + VectorSet(pcjMax,-15.0f,80.0f,15.0f); + VectorScale(pcjMin, sFactArm, pcjMin); + VectorScale(pcjMax, sFactArm, pcjMax); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"rhumerus",pcjflags|RAG_BONE_LIGHTWEIGHT|RAG_UNSNAPPABLE,(4.0f*sRadArm)*fRadScale,pcjMin,pcjMax,500); + VectorSet(pcjMin,-50.0f,-80.0f,-15.0f); + VectorSet(pcjMax,15.0f,40.0f,15.0f); + VectorScale(pcjMin, sFactArm, pcjMin); + VectorScale(pcjMax, sFactArm, pcjMax); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"lhumerus",pcjflags|RAG_BONE_LIGHTWEIGHT|RAG_UNSNAPPABLE,(4.0f*sRadArm)*fRadScale,pcjMin,pcjMax,500); + + VectorSet(pcjMin,-25.0f,-20.0f,-20.0f); + VectorSet(pcjMax,90.0f,20.0f,-20.0f); + VectorScale(pcjMin, sFactArm, pcjMin); + VectorScale(pcjMax, sFactArm, pcjMax); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"rradius",pcjflags|RAG_BONE_LIGHTWEIGHT,(3.0f*sRadArm)*fRadScale,pcjMin,pcjMax,500); + VectorSet(pcjMin,-90.0f,-20.0f,-20.0f); + VectorSet(pcjMax,30.0f,20.0f,-20.0f); + VectorScale(pcjMin, sFactArm, pcjMin); + VectorScale(pcjMax, sFactArm, pcjMax); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"lradius",pcjflags|RAG_BONE_LIGHTWEIGHT,(3.0f*sRadArm)*fRadScale,pcjMin,pcjMax,500); + + + VectorSet(pcjMin,-80.0f,-50.0f,-20.0f); + VectorSet(pcjMax,30.0f,5.0f,20.0f); + VectorScale(pcjMin, sFactLeg, pcjMin); + VectorScale(pcjMax, sFactLeg, pcjMax); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"rfemurYZ",pcjflags|RAG_BONE_LIGHTWEIGHT,(6.0f*sRadLeg)*fRadScale,pcjMin,pcjMax,500); + VectorSet(pcjMin,-60.0f,-5.0f,-20.0f); + VectorSet(pcjMax,50.0f,50.0f,20.0f); + VectorScale(pcjMin, sFactLeg, pcjMin); + VectorScale(pcjMax, sFactLeg, pcjMax); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"lfemurYZ",pcjflags|RAG_BONE_LIGHTWEIGHT,(6.0f*sRadLeg)*fRadScale,pcjMin,pcjMax,500); + + VectorSet(pcjMin,-20.0f,-15.0f,-15.0f); + VectorSet(pcjMax,100.0f,15.0f,15.0f); + VectorScale(pcjMin, sFactLeg, pcjMin); + VectorScale(pcjMax, sFactLeg, pcjMax); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"rtibia",pcjflags|RAG_EFFECTOR|RAG_BONE_LIGHTWEIGHT,(4.0f*sRadLeg)*fRadScale,pcjMin,pcjMax,500); + VectorSet(pcjMin,20.0f,-15.0f,-15.0f); + VectorSet(pcjMax,100.0f,15.0f,15.0f); + VectorScale(pcjMin, sFactLeg, pcjMin); + VectorScale(pcjMax, sFactLeg, pcjMax); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"ltibia",pcjflags|RAG_EFFECTOR|RAG_BONE_LIGHTWEIGHT,(4.0f*sRadLeg)*fRadScale,pcjMin,pcjMax,500); +#else + // old base anim + int pcjflags=RAG_PCJ|RAG_PCJ_POST_MULT|RAG_EFFECTOR; + + VectorSet(pcjMin,-15.0f,-15.0f,-15.0f); + VectorSet(pcjMax,45.0f,15.0f,15.0f); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"lower_lumbar",pcjflags,10.0f,pcjMin,pcjMax,500); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"upper_lumbar",pcjflags,10.0f,pcjMin,pcjMax,500); + VectorSet(pcjMin,-45.0f,-45.0f,-45.0f); + VectorSet(pcjMax,45.0f,45.0f,45.0f); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"thoracic",pcjflags,10.0f,pcjMin,pcjMax,500); + + VectorSet(pcjMin,-10.0f,-10.0f,-90.0f); + VectorSet(pcjMax,10.0f,10.0f,90.0f); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"cranium",pcjflags|RAG_BONE_LIGHTWEIGHT,6.0f,pcjMin,pcjMax,500); + + //VectorSet(pcjMin,-45.0f,-90.0f,-100.0f); + VectorSet(pcjMin,-180.0f,-180.0f,-100.0f); + //VectorSet(pcjMax,60.0f,60.0f,45.0f); + VectorSet(pcjMax,180.0f,180.0f,45.0f); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"rhumerus",pcjflags|RAG_BONE_LIGHTWEIGHT,4.0f,pcjMin,pcjMax,500); + //VectorSet(pcjMin,-45.0f,-60.0f,-45.0f); + VectorSet(pcjMin,-180.0f,-180.0f,-100.0f); + //VectorSet(pcjMax,60.0f,90.0f,100.0f); + VectorSet(pcjMax,180.0f,180.0f,100.0f); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"lhumerus",pcjflags|RAG_BONE_LIGHTWEIGHT,4.0f,pcjMin,pcjMax,500); + + //-120/120 + VectorSet(pcjMin,-120.0f,-20.0f,-20.0f); + VectorSet(pcjMax,50.0f,20.0f,-20.0f); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"rradius",pcjflags|RAG_BONE_LIGHTWEIGHT,3.0f,pcjMin,pcjMax,500); + VectorSet(pcjMin,-120.0f,-20.0f,-20.0f); + VectorSet(pcjMax,5.0f,20.0f,-20.0f); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"lradius",pcjflags|RAG_BONE_LIGHTWEIGHT,3.0f,pcjMin,pcjMax,500); + + VectorSet(pcjMin,-90.0f,-50.0f,-20.0f); + VectorSet(pcjMax,50.0f,20.0f,20.0f); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"rfemurYZ",pcjflags|RAG_BONE_LIGHTWEIGHT,6.0f,pcjMin,pcjMax,500); + VectorSet(pcjMin,-90.0f,-20.0f,-20.0f); + VectorSet(pcjMax,50.0f,50.0f,20.0f); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"lfemurYZ",pcjflags|RAG_BONE_LIGHTWEIGHT,6.0f,pcjMin,pcjMax,500); + + //120 + VectorSet(pcjMin,-20.0f,-15.0f,-15.0f); + VectorSet(pcjMax,120.0f,15.0f,15.0f); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"rtibia",pcjflags|RAG_EFFECTOR|RAG_BONE_LIGHTWEIGHT,4.0f,pcjMin,pcjMax,500); + VectorSet(pcjMin,20.0f,-15.0f,-15.0f); + VectorSet(pcjMax,120.0f,15.0f,15.0f); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"ltibia",pcjflags|RAG_EFFECTOR|RAG_BONE_LIGHTWEIGHT,4.0f,pcjMin,pcjMax,500); +#endif + + + float sRadEArm = 1.2f; + float sRadELeg = 1.2f; + +// int rhand= + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"rhand",RAG_EFFECTOR|RAG_BONE_LIGHTWEIGHT,(6.0f*sRadEArm)*fRadScale); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"lhand",RAG_EFFECTOR|RAG_BONE_LIGHTWEIGHT,(6.0f*sRadEArm)*fRadScale); + //G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"rtarsal",RAG_EFFECTOR|RAG_BONE_LIGHTWEIGHT,(4.0f*sRadELeg)*fRadScale); + //G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"ltarsal",RAG_EFFECTOR|RAG_BONE_LIGHTWEIGHT,(4.0f*sRadELeg)*fRadScale); +// G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"rtibia",RAG_EFFECTOR|RAG_BONE_LIGHTWEIGHT,(4.0f*sRadELeg)*fRadScale); +// G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"ltibia",RAG_EFFECTOR|RAG_BONE_LIGHTWEIGHT,(4.0f*sRadELeg)*fRadScale); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"rtalus",RAG_EFFECTOR|RAG_BONE_LIGHTWEIGHT,(4.0f*sRadELeg)*fRadScale); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"ltalus",RAG_EFFECTOR|RAG_BONE_LIGHTWEIGHT,(4.0f*sRadELeg)*fRadScale); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"rradiusX",RAG_EFFECTOR|RAG_BONE_LIGHTWEIGHT,(6.0f*sRadEArm)*fRadScale); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"lradiusX",RAG_EFFECTOR|RAG_BONE_LIGHTWEIGHT,(6.0f*sRadEArm)*fRadScale); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"rfemurX",RAG_EFFECTOR|RAG_BONE_LIGHTWEIGHT,(10.0f*sRadELeg)*fRadScale); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"lfemurX",RAG_EFFECTOR|RAG_BONE_LIGHTWEIGHT,(10.0f*sRadELeg)*fRadScale); + //G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"ceyebrow",RAG_EFFECTOR|RAG_BONE_LIGHTWEIGHT,10.0f*fRadScale); + G2_Set_Bone_Angles_Rag(ghoul2, mod_a,blist,"ceyebrow",RAG_EFFECTOR|RAG_BONE_LIGHTWEIGHT,5.0f); +//match the currrent animation + if (!G2_RagDollSetup(ghoul2,curTime,true,parms->position,false)) + { + assert(!"failed to add any rag bones"); + return; + } + G2_RagDollCurrentPosition(ghoul2V,model,curTime,parms->angles,parms->position,parms->scale); + int k; + + CRagDollUpdateParams fparms; + VectorCopy(parms->position, fparms.position); + VectorCopy(parms->angles, fparms.angles); + VectorCopy(parms->scale, fparms.scale); + VectorClear(fparms.velocity); + fparms.me = parms->me; + fparms.settleFrame = parms->endFrame; + fparms.groundEnt = parms->groundEnt; + + //Guess I don't need to do this, do I? + G2_ConstructGhoulSkeleton(ghoul2V, curTime, false, parms->scale); + + vec3_t dPos; + VectorCopy(parms->position, dPos); +#ifdef _OLD_STYLE_SETTLE + dPos[2] -= 6; +#endif + + for (k=0;kangles,dPos,parms->scale); + G2_RagDollMatchPosition(); + G2_RagDollSolve(ghoul2V,model,1.0f*(1.0f-k/40.0f),curTime,dPos,false); + } +} + +void G2_SetRagDollBullet(CGhoul2Info &ghoul2,const vec3_t rayStart,const vec3_t hit) +{ + if (!broadsword||!broadsword->integer) + { + return; + } + vec3_t shotDir; + VectorSubtract(hit,rayStart,shotDir); + float len=VectorLength(shotDir); + if (len<1.0f) + { + return; + } + float lenr=1.0f/len; + shotDir[0]*=lenr; + shotDir[1]*=lenr; + shotDir[2]*=lenr; + + bool firstOne=false; + if (broadsword_kickbones&&broadsword_kickbones->integer) + { + int magicFactor13=150.0f; // squared radius multiplier for shot effects + boneInfo_v &blist = ghoul2.mBlist; + for(int i=(int)(blist.size()-1);i>=0;i--) + { + boneInfo_t &bone=blist[i]; + if ((bone.flags & BONE_ANGLES_TOTAL)) + { + if (bone.flags & BONE_ANGLES_RAGDOLL) + { + if (!firstOne) + { + firstOne=true; +#if 0 + int curTime=G2API_GetTime(0); + const mdxaHeader_t *mod_a=G2_GetModA(ghoul2); + int startFrame = 0, endFrame = 0; +#if 1 + TheGhoul2Wraith()->GetAnimFrames(ghoul2.mID, "unconsciousdeadflop01", startFrame, endFrame); + if (startFrame == -1 && endFrame == -1) + { //A bad thing happened! Just use the hardcoded numbers even though they could be wrong. + startFrame = 3573; + endFrame = 3583; + assert(0); + } + G2_Set_Bone_Anim_No_BS(mod_a,blist,"upper_lumbar",startFrame,endFrame-1, + BONE_ANIM_OVERRIDE_FREEZE|BONE_ANIM_BLEND, + 1.0f,curTime,float(startFrame),75,0,true); + G2_Set_Bone_Anim_No_BS(mod_a,blist,"lfemurYZ",startFrame,endFrame-1, + BONE_ANIM_OVERRIDE_FREEZE|BONE_ANIM_BLEND, + 1.0f,curTime,float(startFrame),75,0,true); + G2_Set_Bone_Anim_No_BS(mod_a,blist,"rfemurYZ",startFrame,endFrame-1, + BONE_ANIM_OVERRIDE_FREEZE|BONE_ANIM_BLEND, + 1.0f,curTime,float(startFrame),75,0,true); +#else + TheGhoul2Wraith()->GetAnimFrames(ghoul2.mID, "backdeadflop01", startFrame, endFrame); + if (startFrame == -1 && endFrame == -1) + { //A bad thing happened! Just use the hardcoded numbers even though they could be wrong. + startFrame = 3581; + endFrame = 3592; + assert(0); + } + G2_Set_Bone_Anim_No_BS(mod_a,blist,"upper_lumbar",endFrame,startFrame+1, + BONE_ANIM_OVERRIDE_FREEZE, + -1.0f,curTime,float(endFrame-1),50,0,true); + G2_Set_Bone_Anim_No_BS(mod_a,blist,"lfemurYZ",endFrame,startFrame+1, + BONE_ANIM_OVERRIDE_FREEZE, + -1.0f,curTime,float(endFrame-1),50,0,true); + G2_Set_Bone_Anim_No_BS(mod_a,blist,"rfemurYZ",endFrame,startFrame+1, + BONE_ANIM_OVERRIDE_FREEZE, + -1.0f,curTime,float(endFrame-1),50,0,true); +#endif +#endif + } + + VectorCopy(shotDir,bone.lastShotDir); + vec3_t dir; + VectorSubtract(bone.lastPosition,hit,dir); + len=VectorLength(dir); + if (len<1.0f) + { + len=1.0f; + } + lenr=1.0f/len; + float effect=lenr; + effect*=magicFactor13*effect; // this is cubed, one of them is absorbed by the next calc + bone.velocityEffector[0]=shotDir[0]*(effect+flrand(0.0f,0.05f)); + bone.velocityEffector[1]=shotDir[1]*(effect+flrand(0.0f,0.05f)); + bone.velocityEffector[2]=fabs(shotDir[2])*(effect+flrand(0.0f,0.05f)); +// bone.velocityEffector[0]=shotDir[0]*(effect+flrand(0.0f,0.05f))*flrand(-0.1f,3.0f); +// bone.velocityEffector[1]=shotDir[1]*(effect+flrand(0.0f,0.05f))*flrand(-0.1f,3.0f); +// bone.velocityEffector[2]=fabs(shotDir[2])*(effect+flrand(0.0f,0.05f))*flrand(-0.1f,3.0f); + assert( !Q_isnan(shotDir[2])); + // bone.currentAngles[0]+=flrand(-10.0f*lenr,10.0f*lenr); + // bone.currentAngles[1]+=flrand(-10.0f*lenr,10.0f*lenr); + // bone.currentAngles[2]+=flrand(-10.0f*lenr,10.0f*lenr); + // bone.lastAngles[0]+=flrand(-10.0f*lenr,10.0f*lenr); + // bone.lastAngles[1]+=flrand(-10.0f*lenr,10.0f*lenr); + // bone.lastAngles[2]+=flrand(-10.0f*lenr,10.0f*lenr); + + // go dynamic + bone.firstCollisionTime=G2API_GetTime(0); +// bone.firstCollisionTime=0; + bone.restTime=0; + } + } + } + } +} + + +static float G2_RagSetState(CGhoul2Info &ghoul2, boneInfo_t &bone,int frameNum,const vec3_t origin,bool &resetOrigin) +{ + ragOriginChange=DistanceSquared(origin,bone.extraVec1); + VectorSubtract(origin,bone.extraVec1,ragOriginChangeDir); + + float decay=1.0f; + + int dynamicTime=1000; + int settleTime=1000; + + if (ghoul2.mFlags & GHOUL2_RAG_FORCESOLVE) + { + ragState=ERS_DYNAMIC; + if (frameNum>bone.firstCollisionTime+dynamicTime) + { + VectorCopy(origin,bone.extraVec1); + if (ragOriginChange>15.0f) + { //if we moved, or if this bone is still in solid + bone.firstCollisionTime=frameNum; + } + else + { + // settle out + bone.firstCollisionTime=0; + bone.restTime=frameNum; + ragState=ERS_SETTLING; + } + } + } + else if (bone.firstCollisionTime>0) + { + ragState=ERS_DYNAMIC; + if (frameNum>bone.firstCollisionTime+dynamicTime) + { + VectorCopy(origin,bone.extraVec1); + if (ragOriginChange>15.0f) + { //if we moved, or if this bone is still in solid + bone.firstCollisionTime=frameNum; + } + else + { + // settle out + bone.firstCollisionTime=0; + bone.restTime=frameNum; + ragState=ERS_SETTLING; + } + } +//decay=0.0f; + } + else if (bone.restTime>0) + { + decay=1.0f-(frameNum-bone.restTime)/float(dynamicTime); + if (decay<0.0f) + { + decay=0.0f; + } + if (decay>1.0f) + { + decay=1.0f; + } + float magicFactor8=1.0f; // Power for decay + decay=pow(decay,magicFactor8); + ragState=ERS_SETTLING; + if (frameNum>bone.restTime+settleTime) + { + VectorCopy(origin,bone.extraVec1); + if (ragOriginChange>15.0f) + { + bone.restTime=frameNum; + } + else + { + // stop + bone.restTime=0; + ragState=ERS_SETTLED; + } + } +//decay=0.0f; + } + else + { + if (bone.RagFlags & RAG_PCJ_IK_CONTROLLED) + { + bone.firstCollisionTime=frameNum; + ragState=ERS_DYNAMIC; + } + else if (ragOriginChange>15.0f) + { + bone.firstCollisionTime=frameNum; + ragState=ERS_DYNAMIC; + } + else + { + ragState=ERS_SETTLED; + } + decay=0.0f; + } +// ragState=ERS_SETTLED; +// decay=0.0f; + return decay; +} + +static bool G2_RagDollSetup(CGhoul2Info &ghoul2,int frameNum,bool resetOrigin,const vec3_t origin,bool anyRendered) +{ + int minSurvivingBone=10000; + //int minSurvivingBoneAt=-1; + int minSurvivingBoneAlt=10000; + //int minSurvivingBoneAtAlt=-1; + + assert(ghoul2.mFileName[0]); + boneInfo_v &blist = ghoul2.mBlist; + rag.clear(); + int numRendered=0; + int numNotRendered=0; + //int pelvisAt=-1; + for(size_t i=0; i=0) + { + assert(bone.boneNumberbone.boneNumber) + { + minSurvivingBone=bone.boneNumber; + //minSurvivingBoneAt=i; + } + } + else if (wasRendered) + { + if (minSurvivingBoneAlt>bone.boneNumber) + { + minSurvivingBoneAlt=bone.boneNumber; + //minSurvivingBoneAtAlt=i; + } + } + if ( + anyRendered && + (bone.RagFlags&RAG_WAS_EVER_RENDERED) && + !(bone.RagFlags&RAG_PCJ_MODEL_ROOT) && + !(bone.RagFlags&RAG_PCJ_PELVIS) && + !wasRendered && + (bone.RagFlags&RAG_EFFECTOR) + ) + { + // this thing was rendered in the past, but wasn't now, although other bones were, lets get rid of it +// bone.flags &= ~BONE_ANGLES_RAGDOLL; +// bone.RagFlags = 0; +//Com_OPrintf("Deleted Effector %d\n",i); +// continue; + } + if ((int)rag.size()=0 && + pelvisAt>=0) + { + { + // remove the pelvis as a rag + boneInfo_t &bone=blist[minSurvivingBoneAt]; + bone.flags&=~BONE_ANGLES_RAGDOLL; + bone.RagFlags=0; + } + { + // the root-est bone is now our "pelvis + boneInfo_t &bone=blist[minSurvivingBoneAt]; + VectorSet(bone.minAngles,-14500.0f,-14500.0f,-14500.0f); + VectorSet(bone.maxAngles,14500.0f,14500.0f,14500.0f); + bone.RagFlags|=RAG_PCJ_PELVIS|RAG_PCJ; // this guy is our new "pelvis" + bone.flags |= BONE_ANGLES_POSTMULT; + bone.ragStartTime=G2API_GetTime(0); + } + } + } +#endif + numRags=0; + //int ragStartTime=0; + for(size_t i=0; i=0); + assert(numRagsinteger) + { + return; + } + + if (!params) + { + assert(0); + return; + } + + vec3_t dPos; + VectorCopy(params->position, dPos); +#ifdef _OLD_STYLE_SETTLE + dPos[2] -= 6; +#endif + +// params->DebugLine(handPos,handPos2,false); + int frameNum=G2API_GetTime(0); + CGhoul2Info &ghoul2=ghoul2V[g2Index]; + assert(ghoul2.mFileName[0]); + boneInfo_v &blist = ghoul2.mBlist; + + // hack for freezing ragdoll (no idea if it works) +#if 0 + if (0) + { + // we gotta hack this to basically freeze the timers + for(i=0; i=0) + { + assert(bone.boneNumber=0) + { + assert(bone.boneNumber= 0 && bone2.solidCount > 8) + { + noneInSolid = false; + break; + } + } + + if (noneInSolid) + { //we're settled then + params->RagDollSettled(); + return; + } + else + { + continue; + } +#else + params->RagDollSettled(); + return; +#endif + } + if (G2_WasBoneRendered(ghoul2,bone.boneNumber)) + { + anyRendered=true; + break; + } + } + } + } + + int iters = (ragState == ERS_DYNAMIC) ? 4 : 2; + /* + //bool kicked=false; + if (ragOriginChangeDir[2]<-100.0f) + { + //kicked=true; + //iters*=8; + iters*=2; //rww - changed to this.. it was getting up to around 600 traces at times before (which is insane) + } + */ + if (iters) + { + if (!G2_RagDollSetup(ghoul2,frameNum,resetOrigin,dPos,anyRendered)) + { + return; + } + // ok, now our data structures are compact and set up in topological order + + for (int i=0;iangles,dPos,params->scale); + + if (G2_RagDollSettlePositionNumeroTrois(ghoul2V,dPos,params,curTime)) + { +#if 0 + //effectors are start solid alot, so this was pretty extreme + if (!kicked&&iters<4) + { + kicked=true; + //iters*=4; + iters*=2; + } +#endif + } + //params->position[2] += 16; + G2_RagDollSolve(ghoul2V,g2Index,decay*2.0f,frameNum,dPos,true,params); + } + } + + if (params->me != ENTITYNUM_NONE) + { +#if 0 + vec3_t worldMins,worldMaxs; + worldMins[0]=params->position[0]-17; + worldMins[1]=params->position[1]-17; + worldMins[2]=params->position[2]; + worldMaxs[0]=params->position[0]+17; + worldMaxs[1]=params->position[1]+17; + worldMaxs[2]=params->position[2]; +//Com_OPrintf(va("%f \n",worldMins[2]); +// params->DebugLine(worldMins,worldMaxs,true); +#endif + G2_RagDollCurrentPosition(ghoul2V,g2Index,frameNum,params->angles,params->position,params->scale); +// SV_UnlinkEntity(params->me); +// params->me->SetMins(BB_SHOOTING_SIZE,ragBoneMins); +// params->me->SetMaxs(BB_SHOOTING_SIZE,ragBoneMaxs); +// SV_LinkEntity(params->me); + } +} + +#ifdef _DEBUG +#define _DEBUG_BONE_NAMES +#endif + +static inline char *G2_Get_Bone_Name(CGhoul2Info *ghlInfo, boneInfo_v &blist, int boneNum) +{ + mdxaSkel_t *skel; + mdxaSkelOffsets_t *offsets; + offsets = (mdxaSkelOffsets_t *)((byte *)ghlInfo->aHeader + sizeof(mdxaHeader_t)); + skel = (mdxaSkel_t *)((byte *)ghlInfo->aHeader + sizeof(mdxaHeader_t) + offsets->offsets[0]); + + // look through entire list + for(size_t i=0; iaHeader + sizeof(mdxaHeader_t) + offsets->offsets[blist[i].boneNumber]); + + return skel->name; + } + + // didn't find it + return "BONE_NOT_FOUND"; +} + +char *G2_GetBoneNameFromSkel(CGhoul2Info &ghoul2, int boneNum); + +static void G2_RagDollCurrentPosition(CGhoul2Info_v &ghoul2V,int g2Index,int frameNum,const vec3_t angles,const vec3_t position,const vec3_t scale) +{ + CGhoul2Info &ghoul2=ghoul2V[g2Index]; + assert(ghoul2.mFileName[0]); + G2_GenerateWorldMatrix(angles,position); + G2_ConstructGhoulSkeleton(ghoul2V, frameNum, false, scale); + + float totalWt=0.0f; + int i; + for (i=0;iragBoneMaxs[k]) + { + ragBoneMaxs[k]=ragEffectors[i].currentOrigin[k]; + } + if (ragEffectors[i].currentOrigin[k]0.0f); + int k; + { + float wtInv=1.0f/totalWt; + for (k=0;k<3;k++) + { + ragBoneMaxs[k]-=position[k]; + ragBoneMins[k]-=position[k]; + ragBoneMaxs[k]+=10.0f; + ragBoneMins[k]-=10.0f; + ragBoneCM[k]*=wtInv; + + ragBoneCM[k]=ragEffectors[0].currentOrigin[k]; // use the pelvis + } + } +} + +#ifdef _DEBUG +int ragTraceTime = 0; +int ragSSCount = 0; +int ragTraceCount = 0; +#endif + +void Rag_Trace( trace_t *results, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, const int passEntityNum, const int contentmask, const EG2_Collision eG2TraceType, const int useLod ) +{ +#ifdef _DEBUG + int ragPreTrace = ri.Milliseconds(); +#endif + // AntiAnti: should we set entityNum? + results->entityNum = ENTITYNUM_NONE; + ri.SV_Trace(results, start, mins, maxs, end, passEntityNum, contentmask, eG2TraceType, useLod); + results->entityNum = results->fraction != 1.0 ? ENTITYNUM_WORLD : ENTITYNUM_NONE; + +#ifdef _DEBUG + int ragPostTrace = ri.Milliseconds(); + + ragTraceTime += (ragPostTrace - ragPreTrace); + if (results->startsolid) + { + ragSSCount++; + } + ragTraceCount++; +#endif +} + +//run advanced physics on each bone indivudually +//an adaption of my "exphys" custom game physics model +#define MAX_GRAVITY_PULL 256//512 + +static inline bool G2_BoneOnGround(const vec3_t org, const vec3_t mins, const vec3_t maxs, const int ignoreNum) +{ + trace_t tr; + vec3_t gSpot; + + VectorCopy(org, gSpot); + gSpot[2] -= 1.0f; //seems reasonable to me + + Rag_Trace(&tr, org, mins, maxs, gSpot, ignoreNum, RAG_MASK, G2_NOCOLLIDE, 0); + + if (tr.fraction != 1.0f && !tr.startsolid && !tr.allsolid) + { //not in solid, and hit something. Guess it's ground. + return true; + } + + return false; +} + +static inline bool G2_ApplyRealBonePhysics(boneInfo_t &bone, SRagEffector &e, CRagDollUpdateParams *params, vec3_t goalSpot, const vec3_t goalBase, const vec3_t testMins, const vec3_t testMaxs, + const float gravity, const float mass, const float bounce) +{ + trace_t tr; + vec3_t projectedOrigin; + vec3_t vNorm; + vec3_t ground; + vec3_t usedOrigin; + float velScaling = 0.1f; + float vTotal = 0.0f; + bool boneOnGround = false; + + assert(mass <= 1.0f && mass >= 0.01f); + + if (bone.physicsSettled) + { //then we have no need to continue + return true; + } + + if (goalBase) + { + VectorCopy(goalBase, usedOrigin); + } + else + { + VectorCopy(e.currentOrigin, usedOrigin); + } + + if (gravity) + { + //factor it in before we do anything. + VectorCopy(usedOrigin, ground); + ground[2] -= 1.0f; + + Rag_Trace(&tr, usedOrigin, testMins, testMaxs, ground, params->me, RAG_MASK, G2_NOCOLLIDE, 0); + + if (tr.entityNum == ENTITYNUM_NONE) + { + boneOnGround = false; + } + else + { + boneOnGround = true; + } + + if (!boneOnGround) + { + if (!params->velocity[2]) + { //only increase gravitational pull once the actual entity is still + bone.epGravFactor += gravity; + } + + if (bone.epGravFactor > MAX_GRAVITY_PULL) + { //cap it off if needed + bone.epGravFactor = MAX_GRAVITY_PULL; + } + + bone.epVelocity[2] -= bone.epGravFactor; + } + else + { //if we're sitting on something then reset the gravity factor. + bone.epGravFactor = 0; + } + } + else + { + boneOnGround = G2_BoneOnGround(usedOrigin, testMins, testMaxs, params->me); + } + + if (!bone.epVelocity[0] && !bone.epVelocity[1] && !bone.epVelocity[2]) + { //nothing to do if we have no velocity even after gravity. + VectorCopy(usedOrigin, goalSpot); + return true; + } + + //get the projected origin based on velocity. + VectorMA(usedOrigin, velScaling, bone.epVelocity, projectedOrigin); + + //scale it down based on mass + VectorScale(bone.epVelocity, 1.0f-mass, bone.epVelocity); + + VectorCopy(bone.epVelocity, vNorm); + vTotal = VectorNormalize(vNorm); + + if (vTotal < 1 && boneOnGround) + { //we've pretty much stopped moving anyway, just clear it out then. + VectorClear(bone.epVelocity); + bone.epGravFactor = 0; + VectorCopy(usedOrigin, goalSpot); + return true; + } + + Rag_Trace(&tr, usedOrigin, testMins, testMaxs, projectedOrigin, params->me, RAG_MASK, G2_NOCOLLIDE, 0); + + if (tr.startsolid || tr.allsolid) + { //can't go anywhere from here + return false; + } + + //Go ahead and set it to the trace endpoint regardless of what it hit + VectorCopy(tr.endpos, goalSpot); + + if (tr.fraction == 1.0f) + { //Nothing was in the way. + return true; + } + + if (bounce) + { + vTotal *= bounce; //scale it by bounce + + VectorScale(tr.plane.normal, vTotal, vNorm); //scale the trace plane normal by the bounce factor + + if (vNorm[2] > 0) + { + bone.epGravFactor -= vNorm[2]*(1.0f-mass); //The lighter it is the more gravity will be reduced by bouncing vertically. + if (bone.epGravFactor < 0) + { + bone.epGravFactor = 0; + } + } + + VectorAdd(bone.epVelocity, vNorm, bone.epVelocity); //add it into the existing velocity. + + //I suppose it could be sort of neat to make a game callback here to actual do stuff + //when bones slam into things. But it could be slow too. + /* + if (tr.entityNum != ENTITYNUM_NONE && ent->touch) + { //then call the touch function + ent->touch(ent, &g_entities[tr.entityNum], &tr); + } + */ + } + else + { //if no bounce, kill when it hits something. + bone.epVelocity[0] = 0; + bone.epVelocity[1] = 0; + + if (!gravity) + { + bone.epVelocity[2] = 0; + } + } + return true; +} + +#ifdef _DEBUG_BONE_NAMES +static inline void G2_RagDebugBox(vec3_t mins, vec3_t maxs, int duration) +{ + return; //do something +} + +static inline void G2_RagDebugLine(vec3_t start, vec3_t end, int time, int color, int radius) +{ + return; //do something +} +#endif + +#ifdef _OLD_STYLE_SETTLE +static bool G2_RagDollSettlePositionNumeroTrois(CGhoul2Info_v &ghoul2V, const vec3_t currentOrg, CRagDollUpdateParams *params, int curTime) +{ + haveDesiredPelvisOffset=false; + vec3_t desiredPos; + int i; + + assert(params); + //assert(params->me); //no longer valid, because me is an index! + int ignoreNum=params->me; + + bool anyStartSolid=false; + + vec3_t groundSpot={0,0,0}; + // lets find the floor at our quake origin + { + vec3_t testStart; + VectorCopy(currentOrg,testStart); //last arg is dest + vec3_t testEnd; + VectorCopy(testStart,testEnd); //last arg is dest + testEnd[2]-=200.0f; + + vec3_t testMins; + vec3_t testMaxs; + VectorSet(testMins,-10,-10,-10); + VectorSet(testMaxs,10,10,10); + + { + trace_t tr; + assert( !Q_isnan(testStart[1])); + assert( !Q_isnan(testEnd[1])); + assert( !Q_isnan(testMins[1])); + assert( !Q_isnan(testMaxs[1])); + Rag_Trace(&tr, testStart, testMins, testMaxs, testEnd, ignoreNum, RAG_MASK, G2_NOCOLLIDE, 0/*SV_TRACE_NO_PLAYER*/); + if (tr.entityNum==0) + { + VectorAdvance(testStart,.5f,testEnd,tr.endpos); + } + if (tr.startsolid) + { + //hmmm, punt + VectorCopy(currentOrg,groundSpot); //last arg is dest + groundSpot[2]-=30.0f; + } + else + { + VectorCopy(tr.endpos,groundSpot); //last arg is dest + } + } + } + + for (i=0;i groundSpot[2]) + { + testStart[2]=groundSpot[2]+(e.radius-10.0f); + } + else + { + // lets try higher + testStart[2]=groundSpot[2]+8.0f; + Rag_Trace(&tr,testStart,testMins,testMaxs,testEnd,ignoreNum,RAG_MASK,G2_NOCOLLIDE,0); + if (tr.entityNum==0) + { + VectorAdvance(testStart,.5f,testEnd,tr.endpos); + } + } + + } + if (tr.startsolid) + { + iAmStartSolid=true; + anyStartSolid=true; + // above the origin, so lets slide away + if (e.currentOrigin[2] > groundSpot[2]) + { + if (params) + { + SRagDollEffectorCollision args(e.currentOrigin, tr); + params->EffectorCollision(args); + } + } + else + { + //harumph, we are really screwed + } + } + else + { + vertEffectorTraceFraction = tr.fraction; + if (params && + vertEffectorTraceFraction < .95f && + fabsf(tr.plane.normal[2]) < .707f) + { + SRagDollEffectorCollision args(e.currentOrigin, tr); + args.useTracePlane = true; + params->EffectorCollision(args); + } + } + } + vec3_t effectorGroundSpot; + VectorAdvance(testStart,vertEffectorTraceFraction,testEnd,effectorGroundSpot);// VA(a,t,b,c)-> c := (1-t)a+tb + // trace from the quake origin horzontally to the effector + // gonna choose the maximum of the ground spot or the effector location + // and clamp it to be roughly in the bbox + VectorCopy(groundSpot,testStart); //last arg is dest + if (iAmStartSolid) + { + // we don't have a meaningful ground spot + VectorCopy(e.currentOrigin,testEnd); //last arg is dest + bone.solidCount++; + } + else + { + VectorCopy(effectorGroundSpot,testEnd); //last arg is dest + bone.solidCount = 0; + } + assert( !Q_isnan(testStart[1])); + assert( !Q_isnan(testEnd[1])); + assert( !Q_isnan(testMins[1])); + assert( !Q_isnan(testMaxs[1])); + + float ztest; + + if (testEnd[2]>testStart[2]) + { + ztest=testEnd[2]; + } + else + { + ztest=testStart[2]; + } + if (ztest c := (1-t)a+tb + + float horzontalTraceFraction=0.0f; + vec3_t HorizontalHitSpot={0,0,0}; + { + trace_t tr; + Rag_Trace(&tr,testStart,testMins,testMaxs,testEnd,ignoreNum,RAG_MASK,G2_NOCOLLIDE,0); + if (tr.entityNum==0) + { + VectorAdvance(testStart,.5f,testEnd,tr.endpos); + } + horzontalTraceFraction=tr.fraction; + if (tr.startsolid) + { + horzontalTraceFraction=1.0f; + // punt + VectorCopy(e.currentOrigin,HorizontalHitSpot); + } + else + { + VectorCopy(tr.endpos,HorizontalHitSpot); + int magicFactor46=0.98f; // shorten percetage to make sure we can go down along a wall + //float magicFactor46=0.98f; // shorten percetage to make sure we can go down along a wall + //rww - An..int? + VectorAdvance(tr.endpos,magicFactor46,testStart,HorizontalHitSpot);// VA(a,t,b,c)-> c := (1-t)a+tb + + // roughly speaking this is a wall + if (horzontalTraceFraction<0.9f) + { + + // roughly speaking this is a wall + if (fabsf(tr.plane.normal[2])<0.7f) + { + SRagDollEffectorCollision args(e.currentOrigin, tr); + args.useTracePlane = true; + params->EffectorCollision(args); + } + } + else if (!iAmStartSolid && + effectorGroundSpot[2] < groundSpot[2] - 8.0f) + { + // this is a situation where we have something dangling below the pelvis, we want to find the plane going downhill away from the origin + // for various reasons, without this correction the body will actually move away from places it can fall off. + //gotta run the trace backwards to get a plane + { + trace_t tr; + VectorCopy(effectorGroundSpot,testStart); + VectorCopy(groundSpot,testEnd); + + // this can be a line trace, we just want the plane normal + Rag_Trace(&tr,testEnd,0,0,testStart,ignoreNum,RAG_MASK,G2_NOCOLLIDE,0); + if (tr.entityNum==0) + { + VectorAdvance(testStart,.5f,testEnd,tr.endpos); + } + horzontalTraceFraction=tr.fraction; + if (!tr.startsolid && tr.fraction< 0.7f) + { + SRagDollEffectorCollision args(e.currentOrigin, tr); + args.useTracePlane = true; + params->EffectorCollision(args); + } + } + } + } + } + vec3_t goalSpot={0,0,0}; + // now lets trace down + VectorCopy(HorizontalHitSpot,testStart); + VectorCopy(testStart,testEnd); //last arg is dest + testEnd[2]=e.currentOrigin[2]-30.0f; + { + trace_t tr; + Rag_Trace(&tr,testStart,NULL,NULL,testEnd,ignoreNum,RAG_MASK,G2_NOCOLLIDE,0); + if (tr.entityNum==0) + { + VectorAdvance(testStart,.5f,testEnd,tr.endpos); + } + if (tr.startsolid) + { + // punt, go to the origin I guess + VectorCopy(currentOrg,goalSpot); + } + else + { + VectorCopy(tr.endpos,goalSpot); + int magicFactor47=0.5f; // shorten percentage to make sure we can go down along a wall + VectorAdvance(tr.endpos,magicFactor47,testStart,goalSpot);// VA(a,t,b,c)-> c := (1-t)a+tb + } + } + + // ok now as the horizontal trace fraction approaches zero, we want to head toward the horizontalHitSpot + //geeze I would like some reasonable trace fractions + assert(horzontalTraceFraction>=0.0f&&horzontalTraceFraction<=1.0f); + VectorAdvance(HorizontalHitSpot,horzontalTraceFraction*horzontalTraceFraction,goalSpot,goalSpot);// VA(a,t,b,c)-> c := (1-t)a+tb +#if 0 + if ((bone.RagFlags & RAG_EFFECTOR) && (bone.RagFlags & RAG_BONE_LIGHTWEIGHT)) + { //new rule - don't even bother unless it's a lightweight effector + //rww - Factor object velocity into the final desired spot.. + //We want the limbs with a "light" weight to drag behind the general mass. + //If we got here, we shouldn't be the pelvis or the root, so we should be + //fine to treat as lightweight. However, we can flag bones as being particularly + //light. They're given less downscale for the reduction factor. + vec3_t givenVelocity; + vec3_t vSpot; + trace_t vtr; + float vSpeed = 0; + float verticalSpeed = 0; + float vReductionFactor = 0.03f; + float verticalSpeedReductionFactor = 0.06f; //want this to be more obvious + float lwVReductionFactor = 0.1f; + float lwVerticalSpeedReductionFactor = 0.3f; //want this to be more obvious + + + VectorCopy(params->velocity, givenVelocity); + vSpeed = VectorNormalize(givenVelocity); + vSpeed = -vSpeed; //go in the opposite direction of velocity + + verticalSpeed = vSpeed; + + if (bone.RagFlags & RAG_BONE_LIGHTWEIGHT) + { + vSpeed *= lwVReductionFactor; + verticalSpeed *= lwVerticalSpeedReductionFactor; + } + else + { + vSpeed *= vReductionFactor; + verticalSpeed *= verticalSpeedReductionFactor; + } + + vSpot[0] = givenVelocity[0]*vSpeed; + vSpot[1] = givenVelocity[1]*vSpeed; + vSpot[2] = givenVelocity[2]*verticalSpeed; + VectorAdd(goalSpot, vSpot, vSpot); + + if (vSpot[0] || vSpot[1] || vSpot[2]) + { + Rag_Trace(&vtr, goalSpot, testMins, testMaxs, vSpot, ignoreNum, RAG_MASK, G2_NOCOLLIDE,0); + if (vtr.fraction == 1) + { + VectorCopy(vSpot, goalSpot); + } + } + } +#endif + + int k; + int magicFactor12=0.8f; // dampening of velocity applied + int magicFactor16=10.0f; // effect multiplier of velocity applied + + if (iAmStartSolid) + { + magicFactor16 = 30.0f; + } + + for (k=0;k<3;k++) + { + e.desiredDirection[k]=goalSpot[k]-e.currentOrigin[k]; + e.desiredDirection[k]+=magicFactor16*bone.velocityEffector[k]; + e.desiredDirection[k]+=flrand(-0.75f,0.75f)*flrand(-0.75f,0.75f); + bone.velocityEffector[k]*=magicFactor12; + } + VectorCopy(e.currentOrigin,bone.lastPosition); // last arg is dest + } + return anyStartSolid; +} +#else + +#if 0 +static inline int G2_RagIndexForBoneNum(int boneNum) +{ + for (int i = 0; i < numRags; i++) + { + // these are used for affecting the end result + if (ragBoneData[i].boneNum == boneNum) + { + return i; + } + } + + return -1; +} +#endif + +#ifdef _RAG_PRINT_TEST +void G2_RagPrintMatrix(mdxaBone_t *mat) +{ + char x[1024]; + x[0] = 0; + int n = 0; + while (n < 3) + { + int o = 0; + while (o < 4) + { + strcat(x, va("%f ", mat->matrix[n][o])); + o++; + } + n++; + } + strcat(x, "\n"); + Com_Printf(x); +} +#endif + +void G2_RagGetBoneBasePoseMatrixLow(CGhoul2Info &ghoul2, int boneNum, mdxaBone_t &boneMatrix, mdxaBone_t &retMatrix, vec3_t scale); +void G2_RagGetAnimMatrix(CGhoul2Info &ghoul2, const int boneNum, mdxaBone_t &matrix, const int frame); + +static inline void G2_RagGetWorldAnimMatrix(CGhoul2Info &ghoul2, boneInfo_t &bone, CRagDollUpdateParams *params, mdxaBone_t &retMatrix) +{ + static mdxaBone_t trueBaseMatrix, baseBoneMatrix; + + //get matrix for the settleFrame to use as an ideal + G2_RagGetAnimMatrix(ghoul2, bone.boneNumber, trueBaseMatrix, params->settleFrame); + assert(bone.hasAnimFrameMatrix == params->settleFrame); + + G2_RagGetBoneBasePoseMatrixLow(ghoul2, bone.boneNumber, + trueBaseMatrix, baseBoneMatrix, params->scale); + + //Use params to multiply world coordinate/dir matrix into the + //bone matrix and give us a useable world position + Mat3x4_Multiply(&retMatrix, &worldMatrix, &baseBoneMatrix); + + assert(!Q_isnan(retMatrix.matrix[2][3])); +} + +//get the current pelvis Z direction and the base anim matrix Z direction +//so they can be compared and used to offset -rww +static inline void G2_RagGetPelvisLumbarOffsets(CGhoul2Info &ghoul2, CRagDollUpdateParams *params, vec3_t& pos, vec3_t& dir, vec3_t& animPos, vec3_t& animDir) +{ + static mdxaBone_t final; + static mdxaBone_t x; + //static mdxaBone_t *unused1, *unused2; + //static vec3_t lumbarPos; + + assert(ghoul2.animModel); + int boneIndex = G2_Find_Bone(&ghoul2, ghoul2.mBlist, "pelvis"); + assert(boneIndex != -1); + + G2_RagGetWorldAnimMatrix(ghoul2, ghoul2.mBlist[boneIndex], params, final); + G2API_GiveMeVectorFromMatrix(final, ORIGIN, animPos); + G2API_GiveMeVectorFromMatrix(final, POSITIVE_X, animDir); + + //We have the anim matrix pelvis pos now, so get the normal one as well + int bolt = G2API_AddBolt(&ghoul2, "pelvis"); + G2_GetBoltMatrixLow(ghoul2, bolt, params->scale, x); + Mat3x4_Multiply(&final, &worldMatrix, &x); + G2API_GiveMeVectorFromMatrix(final, ORIGIN, pos); + G2API_GiveMeVectorFromMatrix(final, POSITIVE_X, dir); + + /* + //now get lumbar + boneIndex = G2_Find_Bone(ghoul2.animModel, ghoul2.mBlist, "lower_lumbar"); + assert(boneIndex != -1); + + G2_RagGetWorldAnimMatrix(ghoul2, ghoul2.mBlist[boneIndex], params, final); + G2API_GiveMeVectorFromMatrix(&final, ORIGIN, lumbarPos); + + VectorSubtract(animPos, lumbarPos, animDir); + VectorNormalize(animDir); + + //We have the anim matrix lumbar dir now, so get the normal one as well + G2_GetBoneMatrixLow(ghoul2, boneIndex, params->scale, final, unused1, unused2); + G2API_GiveMeVectorFromMatrix(&final, ORIGIN, lumbarPos); + + VectorSubtract(pos, lumbarPos, dir); + VectorNormalize(dir); + */ +} + +static bool G2_RagDollSettlePositionNumeroTrois(CGhoul2Info_v &ghoul2V, const vec3_t currentOrg, CRagDollUpdateParams *params, int curTime) +{ //now returns true if any bone was in solid, otherwise false + int ignoreNum = params->me; + static int i; + static vec3_t goalSpot; + static trace_t tr; + static trace_t solidTr; + static int k; + static const float velocityDampening = 1.0f; + static const float velocityMultiplier = 60.0f; + static vec3_t testMins; + static vec3_t testMaxs; + vec3_t velDir; + static bool startSolid; + bool anySolid = false; + static mdxaBone_t worldBaseMatrix; + static vec3_t parentOrigin; + static vec3_t basePos; + static vec3_t entScale; + static bool hasDaddy; + static bool hasBasePos; + static vec3_t animPelvisDir, pelvisDir, animPelvisPos, pelvisPos; + + //Maybe customize per-bone? + static const float gravity = 3.0f; + static const float mass = 0.09f; + static const float bounce = 0.0f;//1.3f; + //Bouncing and stuff unfortunately does not work too well at the moment. + //Need to keep a seperate "physics origin" or make the filthy solve stuff + //better. + + bool inAir = false; + + if (params->velocity[0] || params->velocity[1] || params->velocity[2]) + { + inAir = true; + } + + if (!params->scale[0] && !params->scale[1] && !params->scale[2]) + { + VectorSet(entScale, 1.0f, 1.0f, 1.0f); + } + else + { + VectorCopy(params->scale, entScale); + } + + if (broadsword_ragtobase && + broadsword_ragtobase->integer > 1) + { + //grab the pelvis directions to offset base positions for bones + G2_RagGetPelvisLumbarOffsets(ghoul2V[0], params, pelvisPos, pelvisDir, animPelvisPos, + animPelvisDir); + + //don't care about the pitch offsets + pelvisDir[2] = 0; + animPelvisDir[2] = 0; + + /* + vec3_t upelvisPos, uanimPelvisPos; + vec3_t blah; + VectorCopy(pelvisPos, upelvisPos); + VectorCopy(animPelvisPos, uanimPelvisPos); + upelvisPos[2] += 64; + uanimPelvisPos[2] += 64; + + VectorMA(upelvisPos, 32.0f, pelvisDir, blah); + G2_RagDebugLine(upelvisPos, blah, 50, 0x00ff00, 1); + VectorMA(uanimPelvisPos, 32.0f, animPelvisDir, blah); + G2_RagDebugLine(uanimPelvisPos, blah, 50, 0xff0000, 1); + */ + + //just convert to angles now, that's all we'll ever use them for + vectoangles(pelvisDir, pelvisDir); + vectoangles(animPelvisDir, animPelvisDir); + } + + for (i = 0; i < numRags; i++) + { + boneInfo_t &bone = *ragBoneData[i]; + SRagEffector &e = ragEffectors[i]; + + if (inAir) + { + bone.airTime = curTime + 30; + } + + if (bone.RagFlags & RAG_PCJ_PELVIS) + { + VectorSet(goalSpot, params->position[0], params->position[1], (params->position[2]+DEFAULT_MINS_2)+((bone.radius*entScale[2])+2)); + + VectorSubtract(goalSpot, e.currentOrigin, desiredPelvisOffset); + haveDesiredPelvisOffset = true; + VectorCopy(e.currentOrigin, bone.lastPosition); + continue; + } + + if (!(bone.RagFlags & RAG_EFFECTOR)) + { + continue; + } + + if (bone.hasOverGoal) + { //api call was made to override the goal spot + VectorCopy(bone.overGoalSpot, goalSpot); + bone.solidCount = 0; + for (k = 0; k < 3; k++) + { + e.desiredDirection[k] = (goalSpot[k] - e.currentOrigin[k]); + e.desiredDirection[k] += (velocityMultiplier * bone.velocityEffector[k]); + bone.velocityEffector[k] *= velocityDampening; + } + VectorCopy(e.currentOrigin, bone.lastPosition); + + continue; + } + + VectorSet(testMins, -e.radius*entScale[0], -e.radius*entScale[1], -e.radius*entScale[2]); + VectorSet(testMaxs, e.radius*entScale[0], e.radius*entScale[1], e.radius*entScale[2]); + + assert(ghoul2V[0].mBoneCache); + + //get the parent bone's position + hasDaddy = false; + if (bone.boneNumber) + { + assert(ghoul2V[0].animModel); + assert(ghoul2V[0].aHeader); + + if (bone.parentBoneIndex == -1) + { + mdxaSkel_t *skel; + mdxaSkelOffsets_t *offsets; + int bParentIndex, bParentListIndex = -1; + + offsets = (mdxaSkelOffsets_t *)((byte *)ghoul2V[0].aHeader + sizeof(mdxaHeader_t)); + skel = (mdxaSkel_t *)((byte *)ghoul2V[0].aHeader + sizeof(mdxaHeader_t) + offsets->offsets[bone.boneNumber]); + + bParentIndex = skel->parent; + + while (bParentIndex > 0) + { //go upward through hierarchy searching for the first parent that is a rag bone + skel = (mdxaSkel_t *)((byte *)ghoul2V[0].aHeader + sizeof(mdxaHeader_t) + offsets->offsets[bParentIndex]); + bParentIndex = skel->parent; + bParentListIndex = G2_Find_Bone(ghoul2V[0].animModel, ghoul2V[0].mBlist, skel->name); + + if (bParentListIndex != -1) + { + boneInfo_t &pbone = ghoul2V[0].mBlist[bParentListIndex]; + if (pbone.flags & BONE_ANGLES_RAGDOLL) + { //valid rag bone + break; + } + } + + //didn't work out, reset to -1 again + bParentListIndex = -1; + } + + bone.parentBoneIndex = bParentListIndex; + } + + if (bone.parentBoneIndex != -1) + { + boneInfo_t &pbone = ghoul2V[0].mBlist[bone.parentBoneIndex]; + + if (pbone.flags & BONE_ANGLES_RAGDOLL) + { //has origin calculated for us already + VectorCopy(ragEffectors[pbone.ragIndex].currentOrigin, parentOrigin); + hasDaddy = true; + } + } + } + + //get the position this bone would be in if we were in the desired frame + hasBasePos = false; + if (broadsword_ragtobase && + broadsword_ragtobase->integer) + { + vec3_t v, a; + float f; + + G2_RagGetWorldAnimMatrix(ghoul2V[0], bone, params, worldBaseMatrix); + G2API_GiveMeVectorFromMatrix(worldBaseMatrix, ORIGIN, basePos); + + if (broadsword_ragtobase->integer > 1) + { + float fa = AngleNormalize180(animPelvisDir[YAW]-pelvisDir[YAW]); + float d = fa-bone.offsetRotation; + const float tolerance = 16.0f; + + if (d > tolerance || d < -tolerance) + { //don't update unless x degrees away from the ideal to avoid moving goal spots too much if pelvis rotates + bone.offsetRotation = fa; + } + else + { + fa = bone.offsetRotation; + } + //Rotate the point around the pelvis based on the offsets between pelvis positions + VectorSubtract(basePos, animPelvisPos, v); + f = VectorLength(v); + vectoangles(v, a); + a[YAW] -= fa; + AngleVectors(a, v, 0, 0); + VectorNormalize(v); + VectorMA(animPelvisPos, f, v, basePos); + + //re-orient the position of the bone to the current position of the pelvis + VectorSubtract(basePos, animPelvisPos, v); + //push the spots outward? (to stretch the skeleton more) + //v[0] *= 1.5f; + //v[1] *= 1.5f; + VectorAdd(pelvisPos, v, basePos); + } +#if 0 //for debugging frame skeleton + mdxaSkel_t *skel; + mdxaSkelOffsets_t *offsets; + + offsets = (mdxaSkelOffsets_t *)((byte *)ghoul2V[0].aHeader + sizeof(mdxaHeader_t)); + skel = (mdxaSkel_t *)((byte *)ghoul2V[0].aHeader + sizeof(mdxaHeader_t) + offsets->offsets[bone.boneNumber]); + + vec3_t pu; + VectorCopy(basePos, pu); + pu[2] += 32; + if (bone.boneNumber < 11) + { + G2_RagDebugLine(basePos, pu, 50, 0xff00ff, 1); + } + else if (skel->name[0] == 'l') + { + G2_RagDebugLine(basePos, pu, 50, 0xffff00, 1); + } + else if (skel->name[0] == 'r') + { + G2_RagDebugLine(basePos, pu, 50, 0xffffff, 1); + } + else + { + G2_RagDebugLine(basePos, pu, 50, 0x00ffff, 1); + } +#endif + hasBasePos = true; + } + + //Are we in solid? + if (hasDaddy) + { + Rag_Trace(&tr, e.currentOrigin, testMins, testMaxs, parentOrigin, ignoreNum, RAG_MASK, G2_NOCOLLIDE, 0); + //Rag_Trace(&tr, parentOrigin, testMins, testMaxs, e.currentOrigin, ignoreNum, RAG_MASK, G2_NOCOLLIDE, 0); + } + else + { + Rag_Trace(&tr, e.currentOrigin, testMins, testMaxs, params->position, ignoreNum, RAG_MASK, G2_NOCOLLIDE, 0); + } + + if (tr.startsolid || tr.allsolid || tr.fraction != 1.0f) + { //currently in solid, see what we can do about it + vec3_t vSub; + + startSolid = true; + anySolid = true; + + if (hasBasePos)// && bone.solidCount < 32) + { //only go to the base pos for slightly in solid bones +#if 0 //over-compensation + float fl; + float floorBase; + + VectorSubtract(basePos, e.currentOrigin, vSub); + fl = VectorNormalize(vSub); + VectorMA(e.currentOrigin, /*fl*8.0f*/64.0f, vSub, goalSpot); + + floorBase = ((params->position[2]-23)-testMins[2])+8; + + if (goalSpot[2] > floorBase) + { + goalSpot[2] = floorBase; + } +#else //just use the spot directly + VectorCopy(basePos, goalSpot); + goalSpot[2] = (params->position[2]-23)-testMins[2]; +#endif + //Com_Printf("%i: %f %f %f\n", bone.boneNumber, basePos[0], basePos[1], basePos[2]); + } + else + { //if deep in solid want to try to rise up out of solid before hinting back to base + VectorSubtract(e.currentOrigin, params->position, vSub); + VectorNormalize(vSub); + VectorMA(params->position, 40.0f, vSub, goalSpot); + + //should be 1 unit above the ground taking bounding box sizes into account + goalSpot[2] = (params->position[2]-23)-testMins[2]; + } + + //Trace from the entity origin in the direction between the origin and current bone position to + //find a good eventual goal position + Rag_Trace(&tr, params->position, testMins, testMaxs, goalSpot, params->me, RAG_MASK, G2_NOCOLLIDE, 0); + VectorCopy(tr.endpos, goalSpot); + } + else + { + startSolid = false; + +#if 1 //do hinting? + //Hint the bone back to the base origin + if (hasDaddy || hasBasePos) + { + if (hasBasePos) + { + VectorSubtract(basePos, e.currentOrigin, velDir); + } + else + { + VectorSubtract(e.currentOrigin, parentOrigin, velDir); + } + } + else + { + VectorSubtract(e.currentOrigin, params->position, velDir); + } + + if (VectorLength(velDir) > 2.0f) + { //don't bother if already close + VectorNormalize(velDir); + VectorScale(velDir, 8.0f, velDir); + velDir[2] = 0; //don't want to nudge on Z, the gravity will take care of things. + VectorAdd(bone.epVelocity, velDir, bone.epVelocity); + } +#endif + + //Factor the object's velocity into the bone's velocity, by pushing the bone + //opposite the velocity to give the apperance the lighter limbs are being "dragged" + //behind those of greater mass. + if (bone.RagFlags & RAG_BONE_LIGHTWEIGHT) + { + vec3_t vel; + float vellen; + + VectorCopy(params->velocity, vel); + + //Scale down since our velocity scale is different from standard game physics + VectorScale(vel, 0.5f, vel); + + vellen = VectorLength(vel); + + if (vellen > 64.0f) + { //cap it off + VectorScale(vel, 64.0f/vellen, vel); + } + + //Invert the velocity so we go opposite the heavier parts and drag behind + VectorInverse(vel); + + if (vel[2]) + { //want to override entirely instead then + VectorCopy(vel, bone.epVelocity); + } + else + { + VectorAdd(bone.epVelocity, vel, bone.epVelocity); + } + } + + //We're not in solid so we can apply physics freely now. + if (!G2_ApplyRealBonePhysics(bone, e, params, goalSpot, NULL, testMins, testMaxs, gravity, mass, bounce)) + { + // if this is the case then somehow we failed to apply physics/get a good goal spot, just use the ent origin + VectorCopy(params->position, goalSpot); + } + } + + //Set this now so we know what to do for angle limiting + if (startSolid) + { + bone.solidCount++; + + Rag_Trace(&solidTr, params->position, testMins, testMaxs, e.currentOrigin, ignoreNum, RAG_MASK, G2_NOCOLLIDE, 0); + + if (solidTr.fraction != 1.0f && + (solidTr.plane.normal[0] || solidTr.plane.normal[1]) && + (solidTr.plane.normal[2] < 0.1f || solidTr.plane.normal[2] > -0.1f))// && //don't do anything against flat around + // e.currentOrigin[2] > pelvisPos[2]) + { //above pelvis, means not "even" with on ground level + SRagDollEffectorCollision args(e.currentOrigin, tr); + args.useTracePlane = false; + params->EffectorCollision(args); + } + +#ifdef _DEBUG_BONE_NAMES + if (bone.solidCount > 64) + { + char *debugBoneName = G2_Get_Bone_Name(&ghoul2V[0], ghoul2V[0].mBlist, bone.boneNumber); + vec3_t absmin, absmax; + + assert(debugBoneName); + + Com_Printf("High bone (%s, %i) solid count: %i\n", debugBoneName, bone.boneNumber, bone.solidCount); + + VectorAdd(e.currentOrigin, testMins, absmin); + VectorAdd(e.currentOrigin, testMaxs, absmax); + G2_RagDebugBox(absmin, absmax, 50); + + G2_RagDebugLine(e.currentOrigin, goalSpot, 50, 0x00ff00, 1); + } +#endif + } + else + { + bone.solidCount = 0; + } + +#if 0 //standard goalSpot capping? + //unless we are really in solid, we should keep adjustments minimal + if (/*bone.epGravFactor < 64 &&*/ bone.solidCount < 2 && + !inAir) + { + vec3_t moveDist; + const float extent = 32.0f; + float len; + + VectorSubtract(goalSpot, e.currentOrigin, moveDist); + len = VectorLength(moveDist); + + if (len > extent) + { //if greater than the extent then scale the vector down to the extent and factor it back into the goalspot + VectorScale(moveDist, extent/len, moveDist); + VectorAdd(e.currentOrigin, moveDist, goalSpot); + } + } +#endif + + //Set the desired direction based on the goal position and other factors. + for (k = 0; k < 3; k++) + { + e.desiredDirection[k] = (goalSpot[k] - e.currentOrigin[k]); + + if (broadsword_dircap && + broadsword_dircap->value) + { + float cap = broadsword_dircap->value; + + if (bone.solidCount > 5) + { + float solidFactor = bone.solidCount*0.2f; + + if (solidFactor > 16.0f) + { //don't go too high or something ugly might happen + solidFactor = 16.0f; + } + + e.desiredDirection[k] *= solidFactor; + cap *= 8; + } + + if (e.desiredDirection[k] > cap) + { + e.desiredDirection[k] = cap; + } + else if (e.desiredDirection[k] < -cap) + { + e.desiredDirection[k] = -cap; + } + } + + e.desiredDirection[k] += (velocityMultiplier * bone.velocityEffector[k]); + e.desiredDirection[k] += (flrand(-0.75f, 0.75f) * flrand(-0.75f, 0.75f)); + + bone.velocityEffector[k] *= velocityDampening; + } + VectorCopy(e.currentOrigin, bone.lastPosition); + } + + return anySolid; +} +#endif + +static float AngleNormZero(float theta) +{ + float ret=fmodf(theta,360.0f); + if (ret<-180.0f) + { + ret+=360.0f; + } + else if (ret>180.0f) + { + ret-=360.0f; + } + assert(ret>=-180.0f&&ret<=180.0f); + return ret; +} + +static inline void G2_BoneSnap(CGhoul2Info_v &ghoul2V, boneInfo_t &bone, CRagDollUpdateParams *params) +{ + /* + if ( !ri.CGVMLoaded() || !params ) + { + return; + } + + ragCallbackBoneSnap_t *callData = (ragCallbackBoneSnap_t *)ri.GetSharedMemory(); + + callData->entNum = params->me; + strcpy(callData->boneName, G2_Get_Bone_Name(&ghoul2V[0], ghoul2V[0].mBlist, bone.boneNumber)); + + ri.CGVM_RagCallback( RAG_CALLBACK_BONESNAP ); + */ +} + +static void G2_RagDollSolve(CGhoul2Info_v &ghoul2V,int g2Index,float decay,int frameNum,const vec3_t currentOrg,bool limitAngles,CRagDollUpdateParams *params) +{ + + int i; + + CGhoul2Info &ghoul2=ghoul2V[g2Index]; + + mdxaBone_t N; + mdxaBone_t P; + mdxaBone_t temp1; + mdxaBone_t temp2; + mdxaBone_t curRot; + mdxaBone_t curRotInv; + mdxaBone_t Gs[3]; + mdxaBone_t Enew[3]; + + assert(ghoul2.mFileName[0]); + boneInfo_v &blist = ghoul2.mBlist; + + + // END this is the objective function thing + for (i=0;i50.0f) + { + bone.velocityRoot[k]=50.0f; + } + if (bone.velocityRoot[k]<-50.0f) + { + bone.velocityRoot[k]=-50.0f; + } + */ + //No -rww + bone.ragOverrideMatrix.matrix[k][3]=bone.velocityRoot[k]; + } + } + } + else + { + vec3_t delAngles; + VectorClear(delAngles); + + for (k=0;k<3;k++) + { + tAngles[k]+=0.5f; + Create_Matrix(tAngles,&temp2); //dest 2nd arg + tAngles[k]-=0.5f; + Mat3x4_Multiply(&temp1,&P,&temp2); //dest first arg + Mat3x4_Multiply(&Gs[k],&temp1,&N); //dest first arg + + } + + int allSolidCount = 0;//bone.solidCount; + + // fixme precompute this + int numDep=G2_GetBoneDependents(ghoul2,bone.boneNumber,tempDependents,MAX_BONES_RAG); + int j; + int numRagDep=0; + for (j=0;jragIndex; + assert(depIndex>i); // these are supposed to be topologically sorted + assert(ragBoneData[depIndex]); + boneInfo_t &depBone=*ragBoneData[depIndex]; + if (depBone.RagFlags & RAG_EFFECTOR) // rag doll effector + { + // this is a dependent of me, and also a rag + numRagDep++; + for (k=0;k<3;k++) + { + Mat3x4_Multiply(&Enew[k],&Gs[k],&ragBones[depIndex]); //dest first arg + vec3_t tPosition; + tPosition[0]=Enew[k].matrix[0][3]; + tPosition[1]=Enew[k].matrix[1][3]; + tPosition[2]=Enew[k].matrix[2][3]; + + vec3_t change; + VectorSubtract(tPosition,ragEffectors[depIndex].currentOrigin,change); // dest is last arg + float goodness=DotProduct(change,ragEffectors[depIndex].desiredDirection); + assert( !Q_isnan(goodness)); + goodness*=depBone.weight; + delAngles[k]+=goodness; // keep bigger stuff more out of wall or something + assert( !Q_isnan(delAngles[k])); + } + allSolidCount += depBone.solidCount; + } + } + + //bone.solidCount = allSolidCount; + allSolidCount += bone.solidCount; + + VectorCopy(bone.currentAngles,bone.lastAngles); + // Update angles + float magicFactor9=0.75f; // dampfactor for angle changes + float magicFactor1=0.40f; //controls the speed of the gradient descent + float magicFactor32 = 1.5f; + float recip=0.0f; + if (numRagDep) + { + recip=sqrt(4.0f/float(numRagDep)); + } + + if (allSolidCount > 32) + { + magicFactor1 = 0.6f; + } + else if (allSolidCount > 10) + { + magicFactor1 = 0.5f; + } + + if (bone.overGradSpeed) + { //api call was made to specify a speed for this bone + magicFactor1 = bone.overGradSpeed; + } + + float fac=decay*recip*magicFactor1; + assert(fac>=0.0f); +#if 0 + if (bone.RagFlags & RAG_PCJ_PELVIS) + { + magicFactor9=.85f; // we don't want this swinging radically, make the whole thing kindof unstable + } +#endif + if (ragState==ERS_DYNAMIC) + { + magicFactor9=.85f; // we don't want this swinging radically, make the whole thing kindof unstable + } + +#if 1 //constraint breaks? + if (bone.RagFlags & RAG_UNSNAPPABLE) + { + magicFactor32 = 1.0f; + } +#endif + + for (k=0;k<3;k++) + { + bone.currentAngles[k]+=delAngles[k]*fac; + + bone.currentAngles[k]=(bone.lastAngles[k]-bone.currentAngles[k])*magicFactor9 + bone.currentAngles[k]; + bone.currentAngles[k]=AngleNormZero(bone.currentAngles[k]); +// bone.currentAngles[k]=flrand(bone.minAngles[k],bone.maxAngles[k]); +#if 1 //constraint breaks? + if (limitAngles && ( allSolidCount < 32 || (bone.RagFlags & RAG_UNSNAPPABLE) )) //32 tries and still in solid? Then we'll let you move freely +#else + if (limitAngles) +#endif + { + if (!bone.snapped || (bone.RagFlags & RAG_UNSNAPPABLE)) + { + //magicFactor32 += (allSolidCount/32); + + if (bone.currentAngles[k]>bone.maxAngles[k]*magicFactor32) + { + bone.currentAngles[k]=bone.maxAngles[k]*magicFactor32; + } + if (bone.currentAngles[k]bone.maxAngles[k]*magicFactor32) + { + isSnapped = true; + break; + } + if (bone.currentAngles[k]ragIndex; + if (!ragBoneData[depIndex]) + { + continue; + } + boneInfo_t &depBone=*ragBoneData[depIndex]; + + if (depBone.RagFlags & RAG_EFFECTOR) + { + // this is a dependent of me, and also a rag + numRagDep++; + for (k=0;k<3;k++) + { + Mat3x4_Multiply(&Enew[k],&Gs[k],&ragBones[depIndex]); //dest first arg + vec3_t tPosition; + tPosition[0]=Enew[k].matrix[0][3]; + tPosition[1]=Enew[k].matrix[1][3]; + tPosition[2]=Enew[k].matrix[2][3]; + + vec3_t change; + VectorSubtract(tPosition,ragEffectors[depIndex].currentOrigin,change); // dest is last arg + float goodness=DotProduct(change,ragEffectors[depIndex].desiredDirection); + assert( !Q_isnan(goodness)); + goodness*=depBone.weight; + delAngles[k]+=goodness; // keep bigger stuff more out of wall or something + assert( !Q_isnan(delAngles[k])); + } + } + } + + VectorCopy(bone.currentAngles, bone.lastAngles); + + // Update angles + float magicFactor9 = 0.75f; // dampfactor for angle changes + float magicFactor1 = bone.ikSpeed; //controls the speed of the gradient descent + float magicFactor32 = 1.0f; + float recip = 0.0f; + bool freeThisBone = false; + + if (!magicFactor1) + { + magicFactor1 = 0.40f; + } + + recip = sqrt(4.0f/1.0f); + + float fac = (decay*recip*magicFactor1); + assert(fac >= 0.0f); + + if (ragState == ERS_DYNAMIC) + { + magicFactor9 = 0.85f; // we don't want this swinging radically, make the whole thing kindof unstable + } + + + if (!bone.maxAngles[0] && !bone.maxAngles[1] && !bone.maxAngles[2] && + !bone.minAngles[0] && !bone.minAngles[1] && !bone.minAngles[2]) + { + freeThisBone = true; + } + + for (k = 0; k < 3; k++) + { + bone.currentAngles[k] += delAngles[k]*fac; + + bone.currentAngles[k] = (bone.lastAngles[k]-bone.currentAngles[k])*magicFactor9 + bone.currentAngles[k]; + bone.currentAngles[k] = AngleNormZero(bone.currentAngles[k]); + if (limitAngles && !freeThisBone) + { + if (bone.currentAngles[k] > bone.maxAngles[k]*magicFactor32) + { + bone.currentAngles[k] = bone.maxAngles[k]*magicFactor32; + } + if (bone.currentAngles[k] < bone.minAngles[k]*magicFactor32) + { + bone.currentAngles[k] = bone.minAngles[k]*magicFactor32; + } + } + } + Create_Matrix(bone.currentAngles, &temp1); + Mat3x4_Multiply(&temp2, &temp1, bone.baseposeInv); + Mat3x4_Multiply(&bone.ragOverrideMatrix, bone.basepose, &temp2); + //bone.ragOverrideMatrix = *bone.basepose * (temp1 * *bone.baseposeInv); + assert( !Q_isnan(bone.ragOverrideMatrix.matrix[2][3])); + + G2_Generate_MatrixRag(blist, ragBlistIndex[bone.boneNumber]); + } +} + +static void G2_DoIK(CGhoul2Info_v &ghoul2V,int g2Index,CRagDollUpdateParams *params) +{ + int i; + + if (!params) + { + assert(0); + return; + } + + int frameNum=G2API_GetTime(0); + CGhoul2Info &ghoul2=ghoul2V[g2Index]; + assert(ghoul2.mFileName[0]); + + float decay=1.0f; + bool resetOrigin=false; + bool anyRendered=false; + + int iters = 12; //since we don't trace or anything, we can afford this. + + if (iters) + { + if (!G2_RagDollSetup(ghoul2,frameNum,resetOrigin,params->position,anyRendered)) + { + return; + } + + // ok, now our data structures are compact and set up in topological order + for (i=0;iangles,params->position,params->scale); + + G2_IKReposition(params->position, params); + + G2_IKSolve(ghoul2V,g2Index,decay*2.0f,frameNum,params->position,true); + } + } + + if (params->me != ENTITYNUM_NONE) + { + G2_RagDollCurrentPosition(ghoul2V,g2Index,frameNum,params->angles,params->position,params->scale); + } +} + +static int G2_Set_Bone_Angles_IK( + CGhoul2Info &ghoul2, + const mdxaHeader_t *mod_a, + boneInfo_v &blist, + const char *boneName, + const int flags, + const float radius, + const vec3_t angleMin=0, + const vec3_t angleMax=0, + const int blendTime=500) +{ + int index = G2_Find_Bone_Rag(&ghoul2, blist, boneName); + + if (index == -1) + { + index = G2_Add_Bone(ghoul2.animModel, blist, boneName); + } + if (index != -1) + { + boneInfo_t &bone=blist[index]; + bone.flags |= BONE_ANGLES_IK; + bone.flags &= ~BONE_ANGLES_RAGDOLL; + + bone.ragStartTime=G2API_GetTime(0); + bone.radius=radius; + bone.weight=1.0f; + + if (angleMin&&angleMax) + { + VectorCopy(angleMin,bone.minAngles); + VectorCopy(angleMax,bone.maxAngles); + } + else + { + VectorCopy(bone.currentAngles,bone.minAngles); // I guess this isn't a rag pcj then + VectorCopy(bone.currentAngles,bone.maxAngles); + } + if (!bone.lastTimeUpdated) + { + static mdxaBone_t id = + { + { + { 1.0f, 0.0f, 0.0f, 0.0f }, + { 0.0f, 1.0f, 0.0f, 0.0f }, + { 0.0f, 0.0f, 1.0f, 0.0f } + } + }; + memcpy(&bone.ragOverrideMatrix,&id, sizeof(mdxaBone_t)); + VectorClear(bone.anglesOffset); + VectorClear(bone.positionOffset); + VectorClear(bone.velocityEffector); // this is actually a velocity now + VectorClear(bone.velocityRoot); // this is actually a velocity now + VectorClear(bone.lastPosition); + VectorClear(bone.lastShotDir); + bone.lastContents=0; + // if this is non-zero, we are in a dynamic state + bone.firstCollisionTime=bone.ragStartTime; + // if this is non-zero, we are in a settling state + bone.restTime=0; + // if they are both zero, we are in a settled state + + bone.firstTime=0; + + bone.RagFlags=flags; + bone.DependentRagIndexMask=0; + + G2_Generate_MatrixRag(blist,index); // set everything to th id + + VectorClear(bone.currentAngles); + VectorCopy(bone.currentAngles,bone.lastAngles); + } + } + return index; +} + +void G2_InitIK(CGhoul2Info_v &ghoul2V, sharedRagDollUpdateParams_t *parms, int time, const mdxaHeader_t *mod_a, int model) +{ + CGhoul2Info &ghoul2=ghoul2V[model]; + int curTime=time; + boneInfo_v &blist = ghoul2.mBlist; + + G2_GenerateWorldMatrix(parms->angles, parms->position); + G2_ConstructGhoulSkeleton(ghoul2V, curTime, false, parms->scale); + + // new base anim, unconscious flop + int pcjFlags; + + //Only need the standard effectors for this. + pcjFlags = RAG_PCJ | RAG_PCJ_POST_MULT | RAG_EFFECTOR; + + G2_Set_Bone_Angles_IK(ghoul2, mod_a, blist, "rhand", pcjFlags, 6.0f); + G2_Set_Bone_Angles_IK(ghoul2, mod_a, blist, "lhand", pcjFlags, 6.0f); + // G2_Set_Bone_Angles_IK(ghoul2, mod_a,blist,"rtarsal",pcjFlags,4.0f); + // G2_Set_Bone_Angles_IK(ghoul2, mod_a,blist,"ltarsal",pcjFlags,4.0f); + G2_Set_Bone_Angles_IK(ghoul2, mod_a, blist, "rtibia", pcjFlags, 4.0f); + G2_Set_Bone_Angles_IK(ghoul2, mod_a, blist, "ltibia", pcjFlags, 4.0f); + G2_Set_Bone_Angles_IK(ghoul2, mod_a, blist, "rtalus", pcjFlags, 4.0f); + G2_Set_Bone_Angles_IK(ghoul2, mod_a, blist, "ltalus", pcjFlags, 4.0f); + G2_Set_Bone_Angles_IK(ghoul2, mod_a, blist, "rradiusX", pcjFlags, 6.0f); + G2_Set_Bone_Angles_IK(ghoul2, mod_a, blist, "lradiusX", pcjFlags, 6.0f); + G2_Set_Bone_Angles_IK(ghoul2, mod_a, blist, "rfemurX", pcjFlags, 10.0f); + G2_Set_Bone_Angles_IK(ghoul2, mod_a, blist, "lfemurX", pcjFlags, 10.0f); + G2_Set_Bone_Angles_IK(ghoul2, mod_a, blist, "ceyebrow", pcjFlags, 10.0f); +} + +qboolean G2_SetBoneIKState(CGhoul2Info_v &ghoul2, int time, const char *boneName, int ikState, sharedSetBoneIKStateParams_t *params) +{ + model_t *mod_a; + int g2index = 0; + int curTime = time; + CGhoul2Info &g2 = ghoul2[g2index]; + const mdxaHeader_t *rmod_a = G2_GetModA(g2); + + boneInfo_v &blist = g2.mBlist; + mod_a = (model_t *)g2.animModel; + + if (!boneName) + { //null bonename param means it's time to init the ik stuff on this instance + sharedRagDollUpdateParams_t sRDUP; + + if (ikState == IKS_NONE) + { //this means we want to reset the IK state completely.. run through the bone list, and reset all the appropriate flags + size_t i = 0; + while (i < blist.size()) + { //we can't use this method for ragdoll. However, since we expect them to set their anims/angles again on the PCJ + //limb after they reset it gameside, it's reasonable for IK bones. + boneInfo_t &bone = blist[i]; + if (bone.boneNumber != -1) + { + bone.flags &= ~BONE_ANGLES_RAGDOLL; + bone.flags &= ~BONE_ANGLES_IK; + bone.RagFlags = 0; + bone.lastTimeUpdated = 0; + } + i++; + } + return qtrue; + } + assert(params); + + if (!params) + { + return qfalse; + } + + sRDUP.me = 0; + VectorCopy(params->angles, sRDUP.angles); + VectorCopy(params->origin, sRDUP.position); + VectorCopy(params->scale, sRDUP.scale); + VectorClear(sRDUP.velocity); + G2_InitIK(ghoul2, &sRDUP, curTime, rmod_a, g2index); + return qtrue; + } + + if (!rmod_a || !mod_a) + { + return qfalse; + } + + int index = G2_Find_Bone(mod_a, blist, boneName); + + if (index == -1) + { + index = G2_Add_Bone(mod_a, blist, boneName); + } + + if (index == -1) + { //couldn't find or add the bone.. + return qfalse; + } + + boneInfo_t &bone = blist[index]; + + if (ikState == IKS_NONE) + { //remove the bone from the list then, so it has to reinit. I don't think this should hurt anything since + //we don't store bone index handles gameside anywhere. + if (!(bone.flags & BONE_ANGLES_RAGDOLL)) + { //you can't set the ik state to none if it's not a rag/ik bone. + return qfalse; + } + //bone.flags = 0; + //G2_Remove_Bone_Index(blist, index); + //actually, I want to keep it on the rag list, and remove it as an IK bone instead. + bone.flags &= ~BONE_ANGLES_RAGDOLL; + bone.flags |= BONE_ANGLES_IK; + bone.RagFlags &= ~RAG_PCJ_IK_CONTROLLED; + return qtrue; + } + + //need params if we're not resetting. + if (!params) + { + assert(0); + return qfalse; + } + + /* + if (bone.flags & BONE_ANGLES_RAGDOLL) + { //otherwise if the bone is already flagged as rag, then we can't set it again. (non-active ik bones will be BONE_ANGLES_IK, active are considered rag) + return qfalse; + } + */ + + G2_GenerateWorldMatrix(params->angles, params->origin); + G2_ConstructGhoulSkeleton(ghoul2, curTime, false, params->scale); + + int pcjFlags = RAG_PCJ | RAG_PCJ_IK_CONTROLLED | RAG_PCJ_POST_MULT | RAG_EFFECTOR; + + if (params->pcjOverrides) + { + pcjFlags = params->pcjOverrides; + } + + bone.ikSpeed = 0.4f; + VectorClear(bone.ikPosition); + + G2_Set_Bone_Rag(rmod_a, blist, boneName, g2, params->scale, params->origin); + + int startFrame = params->startFrame, endFrame = params->endFrame; + + if (bone.startFrame != startFrame || bone.endFrame != endFrame) + { //if it's already on this anim leave it alone, to allow smooth transitions into IK on the current anim if it is so desired. + G2_Set_Bone_Anim_No_BS(g2, rmod_a, blist, boneName, startFrame, endFrame-1, + BONE_ANIM_OVERRIDE_FREEZE|BONE_ANIM_BLEND, + 1.0f, curTime, float(startFrame), 150, 0, true); + } + + G2_ConstructGhoulSkeleton(ghoul2, curTime, false, params->scale); + + bone.lastTimeUpdated = 0; + G2_Set_Bone_Angles_Rag(g2, rmod_a, blist, boneName, pcjFlags, params->radius, params->pcjMins, params->pcjMaxs, params->blendTime); + + if (!G2_RagDollSetup(g2,curTime,true,params->origin,false)) + { + assert(!"failed to add any rag bones"); + return qfalse; + } + + return qtrue; +} + +qboolean G2_IKMove(CGhoul2Info_v &ghoul2, int time, sharedIKMoveParams_t *params) +{ +#if 0 + model_t *mod_a; + int g2index = 0; + int curTime = time; + CGhoul2Info &g2 = ghoul2[g2index]; + + boneInfo_v &blist = g2.mBlist; + mod_a = (model_t *)g2.animModel; + + if (!mod_a) + { + return qfalse; + } + + int index = G2_Find_Bone(mod_a, blist, params->boneName); + + //don't add here if you can't find it.. ik bones should already be there, because they need to have special stuff done to them anyway. + if (index == -1) + { //couldn't find the bone.. + return qfalse; + } + + if (!params) + { + assert(0); + return qfalse; + } + + if (!(blist[index].flags & BONE_ANGLES_RAGDOLL) && !(blist[index].flags & BONE_ANGLES_IK)) + { //no-can-do, buddy + return qfalse; + } + + VectorCopy(params->desiredOrigin, blist[index].ikPosition); + blist[index].ikSpeed = params->movementSpeed; +#else + int g2index = 0; + int curTime = time; + CGhoul2Info &g2 = ghoul2[g2index]; + + //rwwFIXMEFIXME: Doing this on all bones at the moment, fix this later? + if (!G2_RagDollSetup(g2,curTime,true,params->origin,false)) + { //changed models, possibly. + return qfalse; + } + + for (int i=0;idesiredOrigin, bone.ikPosition); + bone.ikSpeed = params->movementSpeed; + } + } +#endif + return qtrue; +} + +// set the bone list to all unused so the bone transformation routine ignores it. +void G2_Init_Bone_List(boneInfo_v &blist, int numBones) +{ + blist.clear(); + blist.reserve(numBones); +} + +void G2_RemoveRedundantBoneOverrides(boneInfo_v &blist, int *activeBones) +{ + // walk the surface list, removing surface overrides or generated surfaces that are pointing at surfaces that aren't active anymore + for (size_t i=0; imFileName)); + model_t *mod_a = R_GetModelByHandle(mod_m->data.glm->header->animIndex); + + return (G2_Find_Bone(mod_a, ghoul2->mBlist, boneName)); +} + +int G2_Get_Bone_Index(CGhoul2Info* ghoul2, const char* boneName, qboolean bAddIfNotFound) +{ + if (bAddIfNotFound) + { + return G2_Add_Bone(ghoul2->animModel, ghoul2->mBlist, boneName); + } + else + { + return G2_Find_Bone(ghoul2, ghoul2->mBlist, boneName); + } +} \ No newline at end of file diff --git a/code/rd-rend2/G2_misc.cpp b/code/rd-rend2/G2_misc.cpp new file mode 100644 index 0000000000..e4451cf310 --- /dev/null +++ b/code/rd-rend2/G2_misc.cpp @@ -0,0 +1,1988 @@ +#include "server/exe_headers.h" + +#ifndef __Q_SHARED_H + #include "qcommon/q_shared.h" +#endif + +#include "rd-common/tr_common.h" + +#if !defined(TR_LOCAL_H) + #include "tr_local.h" +#endif + +#include "qcommon/matcomp.h" + +#if !defined(G2_H_INC) + #include "ghoul2/G2.h" +#endif + +#if !defined (MINIHEAP_H_INC) + #include "qcommon/MiniHeap.h" +#endif + +#define G2_MODEL_OK(g) ((g)&&(g)->mValid&&(g)->aHeader&&(g)->currentModel&&(g)->animModel) + +#include "server/server.h" +#include +#include "qcommon/ojk_saved_game_helper.h" + +#ifdef _G2_GORE +#include "G2_gore_r2.h" +//#include "G2_gore_r2.h" + +#define GORE_TAG_UPPER (256) +#define GORE_TAG_MASK (~255) +#define MAX_GORE_RECORDS (500) + +static int CurrentTag=GORE_TAG_UPPER+1; +static int CurrentTagUpper=GORE_TAG_UPPER; + +static std::map GoreRecords; +static std::map,int> GoreTagsTemp; // this is a surface index to gore tag map used only + // temporarily during the generation phase so we reuse gore tags per LOD +int goreModelIndex; + +static cvar_t *cg_g2MarksAllModels=NULL; + + +static inline void DestroyR2GoreTexCoordinates(int tag) +{ + R2GoreTextureCoordinates* gTC = FindR2GoreRecord(tag); + if (!gTC) + { + return; + } + gTC->~R2GoreTextureCoordinates(); + //I don't know what's going on here, it should call the destructor for + //this when it erases the record but sometimes it doesn't. -rww +} + + +int AllocR2GoreRecord() +{ + while (GoreRecords.size()>MAX_GORE_RECORDS) + { + int tagHigh=(*GoreRecords.begin()).first&GORE_TAG_MASK; + std::map::iterator it; + R2GoreTextureCoordinates* gTC; + + it = GoreRecords.begin(); + gTC = &(*it).second; + + if (gTC) + { + gTC->~R2GoreTextureCoordinates(); + } + GoreRecords.erase(GoreRecords.begin()); + while (GoreRecords.size()) + { + if (((*GoreRecords.begin()).first&GORE_TAG_MASK)!=tagHigh) + { + break; + } + it = GoreRecords.begin(); + gTC = &(*it).second; + + if (gTC) + { + gTC->~R2GoreTextureCoordinates(); + } + GoreRecords.erase(GoreRecords.begin()); + } + } + int ret=CurrentTag; + GoreRecords[CurrentTag] = R2GoreTextureCoordinates(); + CurrentTag++; + return ret; +} + +void ResetGoreTag() +{ + GoreTagsTemp.clear(); + CurrentTag=CurrentTagUpper; + CurrentTagUpper+=GORE_TAG_UPPER; +} + +R2GoreTextureCoordinates* FindR2GoreRecord(int tag) +{ + std::map::iterator i=GoreRecords.find(tag); + if (i!=GoreRecords.end()) + { + return &(*i).second; + } + return 0; +} + +void *G2_GetGoreRecord(int tag) +{ + return FindR2GoreRecord(tag); +} + +void DeleteR2GoreRecord(int tag) +{ + DestroyR2GoreTexCoordinates(tag); + GoreRecords.erase(tag); +} + +static int CurrentGoreSet=1; // this is a UUID for gore sets +static std::map GoreSets; // map from uuid to goreset + +CGoreSet *FindGoreSet(int goreSetTag) +{ + std::map::iterator f=GoreSets.find(goreSetTag); + if (f!=GoreSets.end()) + { + return (*f).second; + } + return 0; +} + +CGoreSet *NewGoreSet() +{ + CGoreSet *ret=new CGoreSet(CurrentGoreSet++); + GoreSets[ret->mMyGoreSetTag]=ret; + ret->mRefCount = 1; + return ret; +} + +void DeleteGoreSet(int goreSetTag) +{ + std::map::iterator f = GoreSets.find(goreSetTag); + if (f != GoreSets.end()) + { + if ( (*f).second->mRefCount == 0 || (*f).second->mRefCount - 1 == 0 ) + { + delete (*f).second; + GoreSets.erase(f); + } + else + { + (*f).second->mRefCount--; + } + } +} + + +CGoreSet::~CGoreSet() +{ + std::multimap::iterator i; + for (i=mGoreRecords.begin();i!=mGoreRecords.end();i++) + { + DeleteR2GoreRecord((*i).second.mGoreTag); + } +}; +#endif // _SOF2 + +extern mdxaBone_t worldMatrix; +extern mdxaBone_t worldMatrixInv; + +const mdxaBone_t &EvalBoneCache(int index,CBoneCache *boneCache); + +#ifdef _MSC_VER +#pragma warning(disable : 4512) //assignment op could not be genereated +#endif +class CTraceSurface +{ +public: + int surfaceNum; + surfaceInfo_v& rootSList; + const model_t* currentModel; + const int lod; + vec3_t rayStart; + vec3_t rayEnd; + CCollisionRecord* collRecMap; + const int entNum; + const int modelIndex; + const skin_t* skin; +#ifdef _WIN32 + const struct shader_t* cust_shader; +#else + const shader_t* cust_shader; +#endif + intptr_t* TransformedVertsArray; + const EG2_Collision eG2TraceType; + bool hitOne; + float m_fRadius; + +#ifdef _G2_GORE + //gore application thing + float ssize; + float tsize; + float theta; + int goreShader; + CGhoul2Info* ghoul2info; + + // Procedural-gore application things + SSkinGoreData* gore; +#endif + + CTraceSurface( + int initsurfaceNum, + surfaceInfo_v& initrootSList, + const model_t* initcurrentModel, + int initlod, + vec3_t initrayStart, + vec3_t initrayEnd, + CCollisionRecord* initcollRecMap, + int initentNum, + int initmodelIndex, + const skin_t* initskin, + const shader_t* initcust_shader, + intptr_t* initTransformedVertsArray, + const EG2_Collision einitG2TraceType, +#ifdef _G2_GORE + float fRadius, + float initssize, + float inittsize, + float inittheta, + int initgoreShader, + CGhoul2Info* initghoul2info, + SSkinGoreData* initgore +#else + float fRadius +#endif + ) + : surfaceNum(initsurfaceNum) + , rootSList(initrootSList) + , currentModel(initcurrentModel) + , lod(initlod) + , collRecMap(initcollRecMap) + , entNum(initentNum) + , modelIndex(initmodelIndex) + , skin(initskin) + , cust_shader(initcust_shader) + , TransformedVertsArray(initTransformedVertsArray) + , eG2TraceType(einitG2TraceType) + , hitOne(false) +#ifdef _G2_GORE + , m_fRadius(fRadius) + , ssize(initssize) + , tsize(inittsize) + , theta(inittheta) + , goreShader(initgoreShader) + , ghoul2info(initghoul2info) + , gore(initgore) +#else + , m_fRadius(fRadius) +#endif + { + VectorCopy(initrayStart, rayStart); + VectorCopy(initrayEnd, rayEnd); + } + +}; + +// assorted Ghoul 2 functions. +// list all surfaces associated with a model +void G2_List_Model_Surfaces(const char *fileName) +{ + int i, x; + model_t *mod_m = R_GetModelByHandle(RE_RegisterModel(fileName)); + mdxmSurfHierarchy_t *surf; + mdxmHeader_t *mdxm = mod_m->data.glm->header; + + surf = (mdxmSurfHierarchy_t *) ( (byte *)mdxm + mdxm->ofsSurfHierarchy ); + mdxmSurface_t *surface = (mdxmSurface_t *)((byte *)mdxm + mdxm->ofsLODs + sizeof(mdxmLOD_t)); + + for ( x = 0 ; x < mdxm->numSurfaces ; x++) + { + Com_Printf("Surface %i Name %s\n", x, surf->name); + if ( r_verbose->integer ) + { + Com_Printf("Num Descendants %i\n", surf->numChildren); + for (i=0; inumChildren; i++) + { + Com_Printf("Descendant %i\n", surf->childIndexes[i]); + } + } + // find the next surface + surf = (mdxmSurfHierarchy_t *)( (byte *)surf + (size_t)( &((mdxmSurfHierarchy_t *)0)->childIndexes[ surf->numChildren ] )); + surface =(mdxmSurface_t *)( (byte *)surface + surface->ofsEnd ); + } + +} + +// list all bones associated with a model +void G2_List_Model_Bones(const char *fileName, int frame) +{ + int x, i; + mdxaSkel_t *skel; + mdxaSkelOffsets_t *offsets; + model_t *mod_m = R_GetModelByHandle(RE_RegisterModel(fileName)); + model_t *mod_a = R_GetModelByHandle(mod_m->data.glm->header->animIndex); +// mdxaFrame_t *aframe=0; +// int frameSize; + mdxaHeader_t *header = mod_a->data.gla; + + // figure out where the offset list is + offsets = (mdxaSkelOffsets_t *)((byte *)header + sizeof(mdxaHeader_t)); + +// frameSize = (size_t)( &((mdxaFrame_t *)0)->boneIndexes[ header->numBones ] ); + +// aframe = (mdxaFrame_t *)((byte *)header + header->ofsFrames + (frame * frameSize)); + // walk each bone and list it's name + for (x=0; x< header->numBones; x++) + { + skel = (mdxaSkel_t *)((byte *)header + sizeof(mdxaHeader_t) + offsets->offsets[x]); + Com_Printf("Bone %i Name %s\n", x, skel->name); + + Com_Printf("X pos %f, Y pos %f, Z pos %f\n", skel->BasePoseMat.matrix[0][3], skel->BasePoseMat.matrix[1][3], skel->BasePoseMat.matrix[2][3]); + + // if we are in verbose mode give us more details + if (r_verbose->integer) + { + Com_Printf("Num Descendants %i\n", skel->numChildren); + for (i=0; inumChildren; i++) + { + Com_Printf("Num Descendants %i\n", skel->numChildren); + } + } + } +} + + +/************************************************************************************************ + * G2_GetAnimFileName + * obtain the .gla filename for a model + * + * Input + * filename of model + * + * Output + * true if we successfully obtained a filename, false otherwise + * + ************************************************************************************************/ +qboolean G2_GetAnimFileName(const char *fileName, char **filename) +{ + // find the model we want + model_t *mod = R_GetModelByHandle(RE_RegisterModel(fileName)); + + if (mod) + { + mdxmHeader_t *mdxm = mod->data.glm->header; + if (mdxm && mdxm->animName[0] != 0) + { + *filename = mdxm->animName; + return qtrue; + } + } + return qfalse; +} + + +///////////////////////////////////////////////////////////////////// +// +// Code for collision detection for models gameside +// +///////////////////////////////////////////////////////////////////// + +int G2_DecideTraceLod(CGhoul2Info &ghoul2, int useLod) +{ + int returnLod = useLod; + + // if we are overriding the LOD at top level, then we can afford to only check this level of model + if (ghoul2.mLodBias > returnLod) + { + returnLod = ghoul2.mLodBias; + } + assert(G2_MODEL_OK(&ghoul2)); + + mdxmHeader_t *mdxm = ghoul2.currentModel->data.glm->header; + assert(ghoul2.currentModel); + assert(mdxm); + //what about r_lodBias? + + // now ensure that we haven't selected a lod that doesn't exist for this model + if ( returnLod >= mdxm->numLODs ) + { + returnLod = mdxm->numLODs - 1; + } + + return returnLod; +} + +void R_TransformEachSurface( const mdxmSurface_t *surface, vec3_t scale, CMiniHeap *G2VertSpace, intptr_t *TransformedVertsArray, CBoneCache *boneCache) +{ + int j, k; + mdxmVertex_t *v; + float *TransformedVerts; + + // + // deform the vertexes by the lerped bones + // + int *piBoneReferences = (int*) ((byte*)surface + surface->ofsBoneReferences); + + // alloc some space for the transformed verts to get put in + TransformedVerts = (float *)G2VertSpace->MiniHeapAlloc(surface->numVerts * 5 * 4); + TransformedVertsArray[surface->thisSurfaceIndex] = (intptr_t)TransformedVerts; + if (!TransformedVerts) + { + assert(TransformedVerts); + Com_Error(ERR_DROP, "Ran out of transform space for Ghoul2 Models. Adjust G2_MINIHEAP_SIZE in sv_init.cpp.\n"); + } + + // whip through and actually transform each vertex + const int numVerts = surface->numVerts; + v = (mdxmVertex_t *) ((byte *)surface + surface->ofsVerts); + mdxmVertexTexCoord_t *pTexCoords = (mdxmVertexTexCoord_t *) &v[numVerts]; + + // optimisation issue + if ((scale[0] != 1.0) || (scale[1] != 1.0) || (scale[2] != 1.0)) + { + for ( j = 0; j < numVerts; j++ ) + { + vec3_t tempVert, tempNormal; +// mdxmWeight_t *w; + + VectorClear( tempVert ); + VectorClear( tempNormal ); +// w = v->weights; + + const int iNumWeights = G2_GetVertWeights( v ); + + float fTotalWeight = 0.0f; + for ( k = 0 ; k < iNumWeights ; k++ ) + { + int iBoneIndex = G2_GetVertBoneIndex( v, k ); + float fBoneWeight = G2_GetVertBoneWeight( v, k, fTotalWeight, iNumWeights ); + + const mdxaBone_t &bone=EvalBoneCache(piBoneReferences[iBoneIndex],boneCache); + + tempVert[0] += fBoneWeight * ( DotProduct( bone.matrix[0], v->vertCoords ) + bone.matrix[0][3] ); + tempVert[1] += fBoneWeight * ( DotProduct( bone.matrix[1], v->vertCoords ) + bone.matrix[1][3] ); + tempVert[2] += fBoneWeight * ( DotProduct( bone.matrix[2], v->vertCoords ) + bone.matrix[2][3] ); + + tempNormal[0] += fBoneWeight * DotProduct( bone.matrix[0], v->normal ); + tempNormal[1] += fBoneWeight * DotProduct( bone.matrix[1], v->normal ); + tempNormal[2] += fBoneWeight * DotProduct( bone.matrix[2], v->normal ); + } + int pos = j * 5; + + // copy tranformed verts into temp space + TransformedVerts[pos++] = tempVert[0] * scale[0]; + TransformedVerts[pos++] = tempVert[1] * scale[1]; + TransformedVerts[pos++] = tempVert[2] * scale[2]; + // we will need the S & T coors too for hitlocation and hitmaterial stuff + TransformedVerts[pos++] = pTexCoords[j].texCoords[0]; + TransformedVerts[pos] = pTexCoords[j].texCoords[1]; + + v++;// = (mdxmVertex_t *)&v->weights[/*v->numWeights*/surface->maxVertBoneWeights]; + } + } + else + { + int pos = 0; + for ( j = 0; j < numVerts; j++ ) + { + vec3_t tempVert, tempNormal; +// const mdxmWeight_t *w; + + VectorClear( tempVert ); + VectorClear( tempNormal ); +// w = v->weights; + + const int iNumWeights = G2_GetVertWeights( v ); + + float fTotalWeight = 0.0f; + for ( k = 0 ; k < iNumWeights ; k++ ) + { + int iBoneIndex = G2_GetVertBoneIndex( v, k ); + float fBoneWeight = G2_GetVertBoneWeight( v, k, fTotalWeight, iNumWeights ); + + const mdxaBone_t &bone=EvalBoneCache(piBoneReferences[iBoneIndex], boneCache); + + tempVert[0] += fBoneWeight * ( DotProduct( bone.matrix[0], v->vertCoords ) + bone.matrix[0][3] ); + tempVert[1] += fBoneWeight * ( DotProduct( bone.matrix[1], v->vertCoords ) + bone.matrix[1][3] ); + tempVert[2] += fBoneWeight * ( DotProduct( bone.matrix[2], v->vertCoords ) + bone.matrix[2][3] ); + + tempNormal[0] += fBoneWeight * DotProduct( bone.matrix[0], v->normal ); + tempNormal[1] += fBoneWeight * DotProduct( bone.matrix[1], v->normal ); + tempNormal[2] += fBoneWeight * DotProduct( bone.matrix[2], v->normal ); + } + + // copy tranformed verts into temp space + TransformedVerts[pos++] = tempVert[0]; + TransformedVerts[pos++] = tempVert[1]; + TransformedVerts[pos++] = tempVert[2]; + // we will need the S & T coors too for hitlocation and hitmaterial stuff + TransformedVerts[pos++] = pTexCoords[j].texCoords[0]; + TransformedVerts[pos++] = pTexCoords[j].texCoords[1]; + + v++;// = (mdxmVertex_t *)&v->weights[/*v->numWeights*/surface->maxVertBoneWeights]; + } + } +} + +void G2_TransformSurfaces(int surfaceNum, surfaceInfo_v &rootSList, + CBoneCache *boneCache, const model_t *currentModel, int lod, vec3_t scale, CMiniHeap *G2VertSpace, intptr_t* TransformedVertArray, bool secondTimeAround) +{ + int i; + assert(currentModel); + assert(currentModel->data.glm && currentModel->data.glm->header); + // back track and get the surfinfo struct for this surface + const mdxmSurface_t *surface = (mdxmSurface_t *)G2_FindSurface(currentModel, surfaceNum, lod); + const mdxmHierarchyOffsets_t *surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)currentModel->data.glm->header + sizeof(mdxmHeader_t)); + const mdxmSurfHierarchy_t *surfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surface->thisSurfaceIndex]); + + // see if we have an override surface in the surface list + const surfaceInfo_t *surfOverride = G2_FindOverrideSurface(surfaceNum, rootSList); + + // really, we should use the default flags for this surface unless it's been overriden + int offFlags = surfInfo->flags; + + if (surfOverride) + { + offFlags = surfOverride->offFlags; + } + // if this surface is not off, add it to the shader render list + if (!offFlags) + { + + R_TransformEachSurface(surface, scale, G2VertSpace, TransformedVertArray, boneCache); + } + + // if we are turning off all descendants, then stop this recursion now + if (offFlags & G2SURFACEFLAG_NODESCENDANTS) + { + return; + } + + // now recursively call for the children + for (i=0; i< surfInfo->numChildren; i++) + { + G2_TransformSurfaces(surfInfo->childIndexes[i], rootSList, boneCache, currentModel, lod, scale, G2VertSpace, TransformedVertArray, secondTimeAround); + } +} + +// main calling point for the model transform for collision detection. At this point all of the skeleton has been transformed. +#ifdef _G2_GORE +void G2_TransformModel(CGhoul2Info_v& ghoul2, const int frameNum, vec3_t scale, CMiniHeap* G2VertSpace, int useLod, bool ApplyGore, SSkinGoreData* gore) +#else +void G2_TransformModel(CGhoul2Info_v& ghoul2, const int frameNum, vec3_t scale, CMiniHeap* G2VertSpace, int useLod) +#endif +{ + int i, lod; + vec3_t correctScale; + +#if !defined(JK2_MODE) || defined(_G2_GORE) + qboolean firstModelOnly = qfalse; +#endif // !JK2_MODE || _G2_GORE + +#ifndef JK2_MODE + if ( cg_g2MarksAllModels == NULL ) + { + cg_g2MarksAllModels = ri.Cvar_Get( "cg_g2MarksAllModels", "0", 0 ); + } + + if (cg_g2MarksAllModels == NULL || !cg_g2MarksAllModels->integer ) + { + firstModelOnly = qtrue; + } +#endif + +#ifdef _G2_GORE + if (gore && gore->firstModel > 0) + { + firstModelOnly = qfalse; + } +#endif + + VectorCopy(scale, correctScale); + // check for scales of 0 - that's the default I believe + if (!scale[0]) + { + correctScale[0] = 1.0; + } + if (!scale[1]) + { + correctScale[1] = 1.0; + } + if (!scale[2]) + { + correctScale[2] = 1.0; + } + + // walk each possible model for this entity and try rendering it out + for (i=0; i=g.currentModel->numLods) + { + g.mTransformedVertsArray = 0; + if (firstModelOnly) + { + // we don't really need to do multiple models for gore. + return; + } + //do the rest + continue; + } + } + else + { +#endif + lod = G2_DecideTraceLod(g, useLod); +#ifdef _G2_GORE + } +#endif + + mdxmHeader_t *mdxm = g.currentModel->data.glm->header; +#ifndef REND2_SP + // give us space for the transformed vertex array to be put in + if (!(g.mFlags & GHOUL2_ZONETRANSALLOC)) + { +#endif + //do not stomp if we're using zone space + g.mTransformedVertsArray = (intptr_t*)G2VertSpace->MiniHeapAlloc(mdxm->numSurfaces * sizeof(intptr_t)); + if (!g.mTransformedVertsArray) + { + Com_Error(ERR_DROP, "Ran out of transform space for Ghoul2 Models. Adjust G2_MINIHEAP_SIZE in sv_init.cpp.\n"); + } +#ifndef REND2_SP + } +#endif + memset(g.mTransformedVertsArray, 0,mdxm->numSurfaces * sizeof (intptr_t)); + + G2_FindOverrideSurface(-1,g.mSlist); //reset the quick surface override lookup; + // recursively call the model surface transform + + G2_TransformSurfaces(g.mSurfaceRoot, g.mSlist, g.mBoneCache, g.currentModel, lod, correctScale, G2VertSpace, g.mTransformedVertsArray, false); + +#ifdef _G2_GORE + if (ApplyGore && firstModelOnly) + { + // we don't really need to do multiple models for gore. + break; + } +#endif + } +} + + +// work out how much space a triangle takes +static float G2_AreaOfTri(const vec3_t A, const vec3_t B, const vec3_t C) +{ + vec3_t cross, ab, cb; + VectorSubtract(A, B, ab); + VectorSubtract(C, B, cb); + + CrossProduct(ab, cb, cross); + + return VectorLength(cross); +} + +// actually determine the S and T of the coordinate we hit in a given poly +static void G2_BuildHitPointST( const vec3_t A, const float SA, const float TA, + const vec3_t B, const float SB, const float TB, + const vec3_t C, const float SC, const float TC, + const vec3_t P, float *s, float *t,float &bary_i,float &bary_j) +{ + float areaABC = G2_AreaOfTri(A, B, C); + + float i = G2_AreaOfTri(P, B, C) / areaABC; + bary_i=i; + float j = G2_AreaOfTri(A, P, C) / areaABC; + bary_j=j; + float k = G2_AreaOfTri(A, B, P) / areaABC; + + *s = SA * i + SB * j + SC * k; + *t = TA * i + TB * j + TC * k; + + *s=fmod(*s, 1); + if (*s< 0) + { + *s+= 1.0; + } + + *t=fmod(*t, 1); + if (*t< 0) + { + *t+= 1.0; + } + +} + + +// routine that works out given a ray whether or not it hits a poly +static inline qboolean G2_SegmentTriangleTest( const vec3_t start, const vec3_t end, + const vec3_t A, const vec3_t B, const vec3_t C, + qboolean backFaces,qboolean frontFaces,vec3_t returnedPoint,vec3_t returnedNormal, float *denom) +{ + static const float tiny=1E-10f; + vec3_t returnedNormalT; + vec3_t edgeAC; + + VectorSubtract(C, A, edgeAC); + VectorSubtract(B, A, returnedNormalT); + + CrossProduct(returnedNormalT, edgeAC, returnedNormal); + + vec3_t ray; + VectorSubtract(end, start, ray); + + *denom=DotProduct(ray, returnedNormal); + + if (Q_fabs(*denom)0)|| // not accepting back faces + (!frontFaces && *denom<0)) //not accepting front faces + { + return qfalse; + } + + vec3_t toPlane; + VectorSubtract(A, start, toPlane); + + float t=DotProduct(toPlane, returnedNormal)/ *denom; + + if (t<0.0f||t>1.0f) + { + return qfalse; // off segment + } + + VectorScale(ray, t, ray); + + VectorAdd(ray, start, returnedPoint); + + vec3_t edgePA; + VectorSubtract(A, returnedPoint, edgePA); + + vec3_t edgePB; + VectorSubtract(B, returnedPoint, edgePB); + + vec3_t edgePC; + VectorSubtract(C, returnedPoint, edgePC); + + vec3_t temp; + + CrossProduct(edgePA, edgePB, temp); + if (DotProduct(temp, returnedNormal)<0.0f) + { + return qfalse; // off triangle + } + + CrossProduct(edgePC, edgePA, temp); + if (DotProduct(temp,returnedNormal)<0.0f) + { + return qfalse; // off triangle + } + + CrossProduct(edgePB, edgePC, temp); + if (DotProduct(temp, returnedNormal)<0.0f) + { + return qfalse; // off triangle + } + return qtrue; +} + +#ifdef _G2_GORE +struct SVertexTemp +{ + int flags; + int touch; + int newindex; + float tex[2]; + SVertexTemp() + { + touch=0; + } +}; + +#define MAX_GORE_VERTS (3000) +static SVertexTemp GoreVerts[MAX_GORE_VERTS]; +static int GoreIndexCopy[MAX_GORE_VERTS]; +static int GoreTouch=1; + +#define MAX_GORE_INDECIES (6000) +static int GoreIndecies[MAX_GORE_INDECIES]; + +#define GORE_MARGIN (0.0f) +int G2API_GetTime(int argTime); + +// now we at poly level, check each model space transformed poly against the model world transfomed ray +static void G2_GorePolys(const mdxmSurface_t* surface, CTraceSurface& TS, const mdxmSurfHierarchy_t* surfInfo) +{ + int j; + vec3_t basis1; + vec3_t basis2; + vec3_t taxis; + vec3_t saxis; + + if (!TS.gore) + { + return; + } + + if (!TS.gore->useTheta) + { + VectorCopy(TS.gore->uaxis, basis2); + CrossProduct(TS.rayEnd, basis2, basis1); + if (DotProduct(basis1, basis1) < 0.005f) + { //shot dir and slash dir are too close + return; + } + } + + if (TS.gore->useTheta) + { + basis2[0] = 0.0f; + basis2[1] = 0.0f; + basis2[2] = 1.0f; + + CrossProduct(TS.rayEnd, basis2, basis1); + + if (DotProduct(basis1, basis1) < .1f) + { + basis2[0] = 0.0f; + basis2[1] = 1.0f; + basis2[2] = 0.0f; + CrossProduct(TS.rayEnd, basis2, basis1); + } + CrossProduct(TS.rayEnd, basis1, basis2); + } + + // Give me a shot direction not a bunch of zeros :) -Gil + assert(DotProduct(basis1, basis1) > .0001f); + assert(DotProduct(basis2, basis2) > .0001f); + + VectorNormalize(basis1); + VectorNormalize(basis2); + + float c = cos(TS.theta); + float s = sin(TS.theta); + + VectorScale(basis1, .5f * c / TS.tsize, taxis); + VectorMA(taxis, .5f * s / TS.tsize, basis2, taxis); + + VectorScale(basis1, -.5f * s / TS.ssize, saxis); + VectorMA(saxis, .5f * c / TS.ssize, basis2, saxis); + + + float* verts = (float*)TS.TransformedVertsArray[surface->thisSurfaceIndex]; + int numVerts = surface->numVerts; + int flags = 15; + assert(numVerts < MAX_GORE_VERTS); + for (j = 0; j < numVerts; j++) + { + int pos = j * 5; + vec3_t delta; + delta[0] = verts[pos + 0] - TS.rayStart[0]; + delta[1] = verts[pos + 1] - TS.rayStart[1]; + delta[2] = verts[pos + 2] - TS.rayStart[2]; + float s = DotProduct(delta, saxis) + 0.5f; + float t = DotProduct(delta, taxis) + 0.5f; + float depth = DotProduct(delta, TS.rayEnd); + int vflags = 0; + if (s > GORE_MARGIN) + { + vflags |= 1; + } + if (s < 1.0f - GORE_MARGIN) + { + vflags |= 2; + } + if (t > GORE_MARGIN) + { + vflags |= 4; + } + if (t < 1.0f - GORE_MARGIN) + { + vflags |= 8; + } + if (depth < TS.gore->depthEnd) + { + vflags |= 32; + } + vflags = (~vflags); + flags &= vflags; + GoreVerts[j].flags = vflags; + GoreVerts[j].tex[0] = s; + GoreVerts[j].tex[1] = t; + } + if (flags) + { + return; // completely off the gore splotch. + } + + ///////////////////////////////////////////////////////////////// + + int numTris, newNumTris, newNumVerts; + numTris = surface->numTriangles; + mdxmTriangle_t* tris; + tris = (mdxmTriangle_t*)((byte*)surface + surface->ofsTriangles); + verts = (float*)TS.TransformedVertsArray[surface->thisSurfaceIndex]; + newNumTris = 0; + newNumVerts = 0; + GoreTouch++; + + for (j = 0; j < numTris; j++) + { + assert(tris[j].indexes[0] >= 0 && tris[j].indexes[0] < numVerts); + assert(tris[j].indexes[1] >= 0 && tris[j].indexes[1] < numVerts); + assert(tris[j].indexes[2] >= 0 && tris[j].indexes[2] < numVerts); + flags = 15 & + GoreVerts[tris[j].indexes[0]].flags & + GoreVerts[tris[j].indexes[1]].flags & + GoreVerts[tris[j].indexes[2]].flags; + + if (flags) + { + continue; + } + + if (!TS.gore->frontFaces || !TS.gore->backFaces) + { + // we need to back/front face cull + vec3_t e1, e2, n; + + VectorSubtract(&verts[tris[j].indexes[1] * 5], &verts[tris[j].indexes[0] * 5], e1); + VectorSubtract(&verts[tris[j].indexes[2] * 5], &verts[tris[j].indexes[0] * 5], e2); + CrossProduct(e1, e2, n); + + if (DotProduct(TS.rayEnd, n) > 0.0f) + { + if (!TS.gore->frontFaces) + { + continue; + } + } + else + { + if (!TS.gore->backFaces) + { + continue; + } + } + + } + + int k; + + assert(newNumTris * 3 + 3 < MAX_GORE_INDECIES); + for (k = 0; k < 3; k++) + { + if (GoreVerts[tris[j].indexes[k]].touch == GoreTouch) + { + GoreIndecies[newNumTris * 3 + k] = GoreVerts[tris[j].indexes[k]].newindex; + } + else + { + GoreVerts[tris[j].indexes[k]].touch = GoreTouch; + GoreVerts[tris[j].indexes[k]].newindex = newNumVerts; + GoreIndecies[newNumTris * 3 + k] = newNumVerts; + GoreIndexCopy[newNumVerts] = tris[j].indexes[k]; + newNumVerts++; + } + } + newNumTris++; + } + if (!newNumVerts) + { + return; + } + + int newTag; + std::map, int>::iterator f = GoreTagsTemp.find(std::make_pair(goreModelIndex, TS.surfaceNum)); + + if (f == GoreTagsTemp.end()) // need to generate a record + { + newTag = AllocR2GoreRecord(); + CGoreSet* goreSet = 0; + if (TS.ghoul2info->mGoreSetTag) + { + goreSet = FindGoreSet(TS.ghoul2info->mGoreSetTag); + } + if (!goreSet) + { + goreSet = NewGoreSet(); + TS.ghoul2info->mGoreSetTag = goreSet->mMyGoreSetTag; + } + assert(goreSet); + SGoreSurface add; + add.shader = TS.goreShader; + add.mDeleteTime = 0; + if (TS.gore->lifeTime) + { + add.mDeleteTime = G2API_GetTime(0) + TS.gore->lifeTime; + } + add.mFadeTime = TS.gore->fadeOutTime; + add.mFadeRGB = TS.gore->fadeRGB; + add.mGoreTag = newTag; + + add.mGoreGrowStartTime = G2API_GetTime(0); + if (TS.gore->growDuration == -1) + { + add.mGoreGrowEndTime = -1; // set this to -1 to disable growing + } + else + { + add.mGoreGrowEndTime = G2API_GetTime(0) + TS.gore->growDuration; + } + + assert(TS.gore->growDuration != 0); + add.mGoreGrowFactor = (1.0f - TS.gore->goreScaleStartFraction) / (float)(TS.gore->growDuration); //curscale = (curtime-mGoreGrowStartTime)*mGoreGrowFactor; + add.mGoreGrowOffset = TS.gore->goreScaleStartFraction; + + goreSet->mGoreRecords.insert(std::make_pair(TS.surfaceNum, add)); + GoreTagsTemp[std::make_pair(goreModelIndex, TS.surfaceNum)] = newTag; + } + else + { + newTag = (*f).second; + } + + // AntiAnti. R2GoreTextureCoordinates now contains both raw data and structured srfG2GoreSurface_t + // Just not sure what to remove. + R2GoreTextureCoordinates* gore = FindR2GoreRecord(newTag); + if (gore) + { + // fill srfG2GoreSurface_t + //------------------------------------------------------------------------------------------------------------------ + + srfG2GoreSurface_t* goreSurface = (srfG2GoreSurface_t*)R_Malloc(sizeof(srfG2GoreSurface_t), TAG_GHOUL2_GORE, qtrue); + + // cleanup old data + if (gore->tex[TS.lod]) + { + if (gore->tex[TS.lod]->verts) + Z_Free(gore->tex[TS.lod]->verts); + if (gore->tex[TS.lod]->indexes) + Z_Free(gore->tex[TS.lod]->indexes); + Z_Free(gore->tex[TS.lod]); + } + + // set pointer to allocated memory + gore->tex[TS.lod] = (srfG2GoreSurface_t*)goreSurface; + goreSurface->numVerts = newNumVerts; + // allocate space for vertices + goreSurface->verts = (g2GoreVert_t*)R_Malloc(sizeof(g2GoreVert_t) * newNumVerts, TAG_GHOUL2_GORE, qtrue); + + // and set uv for vertices + for (j = 0; j < newNumVerts; j++) + { + goreSurface->verts[j].texCoords[0] = GoreVerts[GoreIndexCopy[j]].tex[0]; + goreSurface->verts[j].texCoords[1] = GoreVerts[GoreIndexCopy[j]].tex[1]; + } + + // set skinning mesh data (weights for bones) for our vertices + mdxmVertex_t* v = (mdxmVertex_t*)((byte*)surface + surface->ofsVerts); + int* boneRef = (int*)((byte*)surface + surface->ofsBoneReferences); + for (j = 0; j < newNumVerts; j++) + { + mdxmVertex_t currentVert = v[GoreIndexCopy[j]]; + VectorCopy(currentVert.vertCoords, goreSurface->verts[j].position); + goreSurface->verts[j].normal = R_VboPackNormal(currentVert.normal); + + int numWeights = G2_GetVertWeights(¤tVert); + float fTotalWeight = 0.0f; + for (int w = 0; w < numWeights; w++) + { + float weight = G2_GetVertBoneWeight(¤tVert, w, fTotalWeight, numWeights); + goreSurface->verts[j].weights[w] = (byte)(weight * 255.0f); + int packedIndex = G2_GetVertBoneIndex(¤tVert, w); + goreSurface->verts[j].bonerefs[w] = boneRef[packedIndex]; + } + } + + // allocate memory for indices and fill them + goreSurface->indexes = (glIndex_t*)R_Malloc(sizeof(glIndex_t) * newNumTris * 3, TAG_GHOUL2_GORE, qtrue); + for (j = 0; j < newNumTris * 3; j++) + { + goreSurface->indexes[j] = GoreIndecies[j] + tr.goreVBOCurrentIndex; + } + goreSurface->numIndexes = newNumTris * 3; + + RB_UpdateGoreVBO(goreSurface); + + } +} +#else +struct SVertexTemp +{ + int flags; +// int touch; +// int newindex; +// float tex[2]; + SVertexTemp() + { +// touch=0; + } +}; + +#define MAX_GORE_VERTS (3000) +static SVertexTemp GoreVerts[MAX_GORE_VERTS]; +#endif + +// now we're at poly level, check each model space transformed poly against the model world transfomed ray +static bool G2_TracePolys(const mdxmSurface_t *surface, const mdxmSurfHierarchy_t *surfInfo, CTraceSurface &TS) +{ + int j, numTris; + + // whip through and actually transform each vertex + const mdxmTriangle_t *tris = (mdxmTriangle_t *) ((byte *)surface + surface->ofsTriangles); + const float *verts = (float *)TS.TransformedVertsArray[surface->thisSurfaceIndex]; + numTris = surface->numTriangles; + for ( j = 0; j < numTris; j++ ) + { + float face; + vec3_t hitPoint, normal; + // determine actual coords for this triangle + const float *point1 = &verts[(tris[j].indexes[0] * 5)]; + const float *point2 = &verts[(tris[j].indexes[1] * 5)]; + const float *point3 = &verts[(tris[j].indexes[2] * 5)]; + // did we hit it? + int i; + if (G2_SegmentTriangleTest(TS.rayStart, TS.rayEnd, point1, point2, point3, qtrue, qtrue, hitPoint, normal, &face)) + { // find space in the collision records for this record + for (i=0; ithisSurfaceIndex; + newCol.mModelIndex = TS.modelIndex; + if (face>0) + { + newCol.mFlags = G2_FRONTFACE; + } + else + { + newCol.mFlags = G2_BACKFACE; + } + + VectorSubtract(hitPoint, TS.rayStart, distVect); + newCol.mDistance = VectorLength(distVect); + assert(!Q_isnan(newCol.mDistance)); + + // put the hit point back into world space + TransformAndTranslatePoint(hitPoint, newCol.mCollisionPosition, &worldMatrix); + + // transform normal (but don't translate) into world angles + TransformPoint(normal, newCol.mCollisionNormal, &worldMatrix); + VectorNormalize(newCol.mCollisionNormal); + + newCol.mMaterial = newCol.mLocation = 0; + + // Determine our location within the texture, and barycentric coordinates + G2_BuildHitPointST(point1, point1[3], point1[4], + point2, point2[3], point2[4], + point3, point3[3], point3[4], + hitPoint, &x_pos, &y_pos,newCol.mBarycentricI,newCol.mBarycentricJ); + +/* + const shader_t *shader = 0; + // now, we know what surface this hit belongs to, we need to go get the shader handle so we can get the correct hit location and hit material info + if ( cust_shader ) + { + shader = cust_shader; + } + else if ( skin ) + { + int j; + + // match the surface name to something in the skin file + shader = tr.defaultShader; + for ( j = 0 ; j < skin->numSurfaces ; j++ ) + { + // the names have both been lowercased + if ( !strcmp( skin->surfaces[j]->name, surfInfo->name ) ) + { + shader = skin->surfaces[j]->shader; + break; + } + } + } + else + { + shader = R_GetShaderByHandle( surfInfo->shaderIndex ); + } + + // do we even care to decide what the hit or location area's are? If we don't have them in the shader there is little point + if ((shader->hitLocation) || (shader->hitMaterial)) + { + // ok, we have a floating point position. - determine location in data we need to look at + if (shader->hitLocation) + { + newCol.mLocation = *(hitMatReg[shader->hitLocation].loc + + ((int)(y_pos * hitMatReg[shader->hitLocation].height) * hitMatReg[shader->hitLocation].width) + + ((int)(x_pos * hitMatReg[shader->hitLocation].width))); + Com_Printf("G2_TracePolys hit location: %d\n", newCol.mLocation); + } + + if (shader->hitMaterial) + { + newCol.mMaterial = *(hitMatReg[shader->hitMaterial].loc + + ((int)(y_pos * hitMatReg[shader->hitMaterial].height) * hitMatReg[shader->hitMaterial].width) + + ((int)(x_pos * hitMatReg[shader->hitMaterial].width))); + } + } +*/ + // exit now if we should + if (TS.eG2TraceType == EG2_Collision::G2_RETURNONHIT) + { + TS.hitOne = true; + return true; + } + + break; + } + } + if (i == MAX_G2_COLLISIONS) + { + //It happens. And the assert is bugging me. + TS.hitOne = true; //force stop recursion + return true; // return true to avoid wasting further time, but no hit will result without a record + } + } + } + return false; +} + + +// now we're at poly level, check each model space transformed poly against the model world transfomed ray +static bool G2_RadiusTracePolys( + const mdxmSurface_t *surface, + CTraceSurface &TS + ) +{ + int j; + vec3_t basis1; + vec3_t basis2; + vec3_t taxis; + vec3_t saxis; + + basis2[0]=0.0f; + basis2[1]=0.0f; + basis2[2]=1.0f; + + vec3_t v3RayDir; + VectorSubtract(TS.rayEnd, TS.rayStart, v3RayDir); + + CrossProduct(v3RayDir,basis2,basis1); + + if (DotProduct(basis1,basis1)<.1f) + { + basis2[0]=0.0f; + basis2[1]=1.0f; + basis2[2]=0.0f; + CrossProduct(v3RayDir,basis2,basis1); + } + + CrossProduct(v3RayDir,basis1,basis2); + // Give me a shot direction not a bunch of zeros :) -Gil +// assert(DotProduct(basis1,basis1)>.0001f); +// assert(DotProduct(basis2,basis2)>.0001f); + + VectorNormalize(basis1); + VectorNormalize(basis2); + + const float c=cos(0.0f);//theta + const float s=sin(0.0f);//theta + + VectorScale(basis1, 0.5f * c / TS.m_fRadius,taxis); + VectorMA(taxis, 0.5f * s / TS.m_fRadius,basis2,taxis); + + VectorScale(basis1,-0.5f * s /TS.m_fRadius,saxis); + VectorMA( saxis, 0.5f * c /TS.m_fRadius,basis2,saxis); + + const float * const verts = (float *)TS.TransformedVertsArray[surface->thisSurfaceIndex]; + const int numVerts = surface->numVerts; + + int flags=63; + //rayDir/=lengthSquared(raydir); + const float f = VectorLengthSquared(v3RayDir); + v3RayDir[0]/=f; + v3RayDir[1]/=f; + v3RayDir[2]/=f; + + for ( j = 0; j < numVerts; j++ ) + { + const int pos=j*5; + vec3_t delta; + delta[0]=verts[pos+0]-TS.rayStart[0]; + delta[1]=verts[pos+1]-TS.rayStart[1]; + delta[2]=verts[pos+2]-TS.rayStart[2]; + const float s=DotProduct(delta,saxis)+0.5f; + const float t=DotProduct(delta,taxis)+0.5f; + const float u=DotProduct(delta,v3RayDir); + int vflags=0; + + if (s>0) + { + vflags|=1; + } + if (s<1) + { + vflags|=2; + } + if (t>0) + { + vflags|=4; + } + if (t<1) + { + vflags|=8; + } + if (u>0) + { + vflags|=16; + } + if (u<1) + { + vflags|=32; + } + + vflags=(~vflags); + flags&=vflags; + GoreVerts[j].flags=vflags; + } + + if (flags) + { + return false; // completely off the gore splotch (so presumably hit nothing? -Ste) + } + const int numTris = surface->numTriangles; + const mdxmTriangle_t * const tris = (mdxmTriangle_t *) ((byte *)surface + surface->ofsTriangles); + + for ( j = 0; j < numTris; j++ ) + { + assert(tris[j].indexes[0]>=0&&tris[j].indexes[0]=0&&tris[j].indexes[1]=0&&tris[j].indexes[2]thisSurfaceIndex; + newCol.mModelIndex = TS.modelIndex; +// if (face>0) +// { + newCol.mFlags = G2_FRONTFACE; +// } +// else +// { +// newCol.mFlags = G2_BACKFACE; +// } + + //get normal from triangle + const float *A = &verts[(tris[j].indexes[0] * 5)]; + const float *B = &verts[(tris[j].indexes[1] * 5)]; + const float *C = &verts[(tris[j].indexes[2] * 5)]; + vec3_t normal; + vec3_t edgeAC, edgeBA; + + VectorSubtract(C, A, edgeAC); + VectorSubtract(B, A, edgeBA); + CrossProduct(edgeBA, edgeAC, normal); + + // transform normal (but don't translate) into world angles + TransformPoint(normal, newCol.mCollisionNormal, &worldMatrix); + VectorNormalize(newCol.mCollisionNormal); + + newCol.mMaterial = newCol.mLocation = 0; + // exit now if we should + if (TS.eG2TraceType == EG2_Collision::G2_RETURNONHIT) + { + TS.hitOne = true; + return true; + } + + vec3_t distVect; +#if 0 + //i don't know the hitPoint, but let's just assume it's the first vert for now... + float *hitPoint = (float *)A; +#else + //yeah, I want the collision point. Let's work out the impact point on the triangle. -rww + vec3_t hitPoint; + float side, side2; + float dist; + float third = -(A[0]*(B[1]*C[2] - C[1]*B[2]) + B[0]*(C[1]*A[2] - A[1]*C[2]) + C[0]*(A[1]*B[2] - B[1]*A[2]) ); + + VectorSubtract(TS.rayEnd, TS.rayStart, distVect); + side = normal[0]*TS.rayStart[0] + normal[1]*TS.rayStart[1] + normal[2]*TS.rayStart[2] + third; + side2 = normal[0]*distVect[0] + normal[1]*distVect[1] + normal[2]*distVect[2]; + if (fabsf(side2) < 1E-8f) + { + //i don't know the hitPoint, but let's just assume it's the first vert for now... + VectorSubtract(A, TS.rayStart, distVect); + dist = VectorLength(distVect); + VectorSubtract(TS.rayEnd, TS.rayStart, distVect); + VectorMA(TS.rayStart, dist / VectorLength(distVect), distVect, hitPoint); + } + else + { + dist = side / side2; + VectorMA(TS.rayStart, -dist, distVect, hitPoint); + } +#endif + + VectorSubtract(hitPoint, TS.rayStart, distVect); + newCol.mDistance = VectorLength(distVect); + assert(!Q_isnan(newCol.mDistance)); + + // put the hit point back into world space + TransformAndTranslatePoint(hitPoint, newCol.mCollisionPosition, &worldMatrix); + newCol.mBarycentricI = newCol.mBarycentricJ = 0.0f; + + break; + } + } + if (i==MAX_G2_COLLISIONS) + { + //assert(i!=MAX_G2_COLLISIONS); // run out of collision record space - happens OFTEN + TS.hitOne = true; //force stop recursion + return true; // return true to avoid wasting further time, but no hit will result without a record + } + } + } + + return false; +} + + +// look at a surface and then do the trace on each poly +static void G2_TraceSurfaces(CTraceSurface &TS) +{ + int i; + // back track and get the surfinfo struct for this surface + assert(TS.currentModel); + assert(TS.currentModel->data.glm && TS.currentModel->data.glm->header); + const mdxmSurface_t *surface = (mdxmSurface_t *)G2_FindSurface(TS.currentModel, TS.surfaceNum, TS.lod); + const mdxmHierarchyOffsets_t *surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)TS.currentModel->data.glm->header + sizeof(mdxmHeader_t)); + const mdxmSurfHierarchy_t *surfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surface->thisSurfaceIndex]); + + // see if we have an override surface in the surface list + const surfaceInfo_t *surfOverride = G2_FindOverrideSurface(TS.surfaceNum, TS.rootSList); + + // don't allow recursion if we've already hit a polygon + if (TS.hitOne) + { + return; + } + + // really, we should use the default flags for this surface unless it's been overriden + int offFlags = surfInfo->flags; + + // set the off flags if we have some + if (surfOverride) + { + offFlags = surfOverride->offFlags; + } + + // if this surface is not off, try to hit it + if (!offFlags) + { +#ifdef _G2_GORE + if (TS.collRecMap) + { +#endif + if (!(Q_fabs(TS.m_fRadius) < 0.1)) // if not a point-trace + { + // .. then use radius check + // + if (G2_RadiusTracePolys(surface, // const mdxmSurface_t *surface, + TS + ) + && (TS.eG2TraceType == EG2_Collision::G2_RETURNONHIT) + ) + { + TS.hitOne = true; + return; + } + } + else + { + // go away and trace the polys in this surface + if (G2_TracePolys(surface, surfInfo, TS) + && (TS.eG2TraceType == EG2_Collision::G2_RETURNONHIT) + ) + { + // ok, we hit one, *and* we want to return instantly because the returnOnHit is set + // so indicate we've hit one, so other surfaces don't get hit and return + TS.hitOne = true; + return; + } + } +#ifdef _G2_GORE + } + else + { + G2_GorePolys(surface, TS, surfInfo); + } +#endif + } + + // if we are turning off all descendants, then stop this recursion now + if (offFlags & G2SURFACEFLAG_NODESCENDANTS) + { + return; + } + + // now recursively call for the children + for (i=0; i< surfInfo->numChildren && !TS.hitOne; i++) + { + TS.surfaceNum = surfInfo->childIndexes[i]; + G2_TraceSurfaces(TS); + } +} + +#ifdef _G2_GORE +void G2_TraceModels(CGhoul2Info_v& ghoul2, vec3_t rayStart, vec3_t rayEnd, CCollisionRecord* collRecMap, int entNum, EG2_Collision eG2TraceType, int useLod, float fRadius, float ssize, float tsize, float theta, int shader, SSkinGoreData* gore, qboolean skipIfLODNotMatch) +#else +void G2_TraceModels(CGhoul2Info_v& ghoul2, vec3_t rayStart, vec3_t rayEnd, CCollisionRecord* collRecMap, int entNum, EG2_Collision eG2TraceType, int useLod, float fRadius) +#endif +{ + int i, lod; + skin_t* skin; + shader_t* cust_shader; +#if !defined(JK2_MODE) || defined(_G2_GORE) + qboolean firstModelOnly = qfalse; +#endif // !JK2_MODE || _G2_GORE + int firstModel = 0; + +#ifndef JK2_MODE + if ( cg_g2MarksAllModels == NULL ) + { + cg_g2MarksAllModels = ri.Cvar_Get( "cg_g2MarksAllModels", "0", 0 ); + } + + if (cg_g2MarksAllModels == NULL + || !cg_g2MarksAllModels->integer ) + { + firstModelOnly = qtrue; + } +#endif // !JK2_MODE + +#ifdef _G2_GORE + if (gore && gore->firstModel > 0) + { + firstModel = gore->firstModel; + firstModelOnly = qfalse; + } +#endif + + // walk each possible model for this entity and try tracing against it + for (i = firstModel; i < ghoul2.size(); i++) + { + CGhoul2Info& g = ghoul2[i]; +#ifdef _G2_GORE + goreModelIndex = i; + // don't bother with models that we don't care about. + if (g.mModelindex == -1) + { + continue; + } +#endif + // don't bother with models that we don't care about. + if (!g.mValid) + { + continue; + } + assert(G2_MODEL_OK(&ghoul2[i])); + // do we really want to collide with this object? + if (g.mFlags & GHOUL2_NOCOLLIDE) + { + continue; + } + + cust_shader = (g.mCustomShader) + ? (shader_t*)R_GetShaderByHandle(g.mCustomShader) + : NULL; + + // figure out the custom skin thing + skin = (g.mSkin > 0 && g.mSkin < tr.numSkins) + ? R_GetSkinByHandle(g.mSkin) + : NULL; + + lod = G2_DecideTraceLod(ghoul2[i],useLod); + +#ifndef JK2_MODE + if ( skipIfLODNotMatch ) + {//we only want to hit this SPECIFIC LOD... + if ( lod != useLod ) + {//doesn't match, skip this model + continue; + } + } +#endif + //reset the quick surface override lookup + G2_FindOverrideSurface(-1, ghoul2[i].mSlist); + +#ifdef _G2_GORE + CTraceSurface TS(g.mSurfaceRoot, ghoul2[i].mSlist, (model_t *)ghoul2[i].currentModel, lod, rayStart, rayEnd, collRecMap, entNum, i, skin, cust_shader, ghoul2[i].mTransformedVertsArray, eG2TraceType, fRadius, ssize, tsize, theta, shader, &g, gore); +#else + CTraceSurface TS(g.mSurfaceRoot, ghoul2[i].mSlist, (model_t *)ghoul2[i].currentModel, lod, rayStart, rayEnd, collRecMap, entNum, i, skin, cust_shader, ghoul2[i].mTransformedVertsArray, eG2TraceType, fRadius); +#endif + // start the surface recursion loop + G2_TraceSurfaces(TS); + + // if we've hit one surface on one model, don't bother doing the rest + if (TS.hitOne) + { + break; + } +#ifdef _G2_GORE + if (!collRecMap&&firstModelOnly) + { + // we don't really need to do multiple models for gore. + break; + } +#endif + } +} + +void TransformPoint (const vec3_t in, vec3_t out, mdxaBone_t *mat) { + for (int i=0;i<3;i++) + { + out[i]= in[0]*mat->matrix[i][0] + in[1]*mat->matrix[i][1] + in[2]*mat->matrix[i][2]; + } +} + +void TransformAndTranslatePoint (const vec3_t in, vec3_t out, mdxaBone_t *mat) { + + for (int i=0;i<3;i++) + { + out[i]= in[0]*mat->matrix[i][0] + in[1]*mat->matrix[i][1] + in[2]*mat->matrix[i][2] + mat->matrix[i][3]; + } +} + + +// create a matrix using a set of angles +void Create_Matrix(const float *angle, mdxaBone_t *matrix) +{ + vec3_t axis[3]; + + // convert angles to axis + AnglesToAxis( angle, axis ); + matrix->matrix[0][0] = axis[0][0]; + matrix->matrix[1][0] = axis[0][1]; + matrix->matrix[2][0] = axis[0][2]; + + matrix->matrix[0][1] = axis[1][0]; + matrix->matrix[1][1] = axis[1][1]; + matrix->matrix[2][1] = axis[1][2]; + + matrix->matrix[0][2] = axis[2][0]; + matrix->matrix[1][2] = axis[2][1]; + matrix->matrix[2][2] = axis[2][2]; + + matrix->matrix[0][3] = 0; + matrix->matrix[1][3] = 0; + matrix->matrix[2][3] = 0; + + +} + +// given a matrix, generate the inverse of that matrix +void Inverse_Matrix(mdxaBone_t *src, mdxaBone_t *dest) +{ + int i, j; + + for (i = 0; i < 3; i++) + { + for (j = 0; j < 3; j++) + { + dest->matrix[i][j]=src->matrix[j][i]; + } + } + for (i = 0; i < 3; i++) + { + dest->matrix[i][3]=0; + for (j = 0; j < 3; j++) + { + dest->matrix[i][3]-=dest->matrix[i][j]*src->matrix[j][3]; + } + } +} + +// generate the world matrix for a given set of angles and origin - called from lots of places +void G2_GenerateWorldMatrix(const vec3_t angles, const vec3_t origin) +{ + Create_Matrix(angles, &worldMatrix); + worldMatrix.matrix[0][3] = origin[0]; + worldMatrix.matrix[1][3] = origin[1]; + worldMatrix.matrix[2][3] = origin[2]; + + Inverse_Matrix(&worldMatrix, &worldMatrixInv); +} + +// go away and determine what the pointer for a specific surface definition within the model definition is +void* G2_FindSurface(const model_s* mod, int index, int lod) +{ + // damn include file dependancies + mdxmHeader_t *mdxm = mod->data.glm->header; + + // point at first lod list + byte *current = (byte*)((size_t)mdxm + (size_t)mdxm->ofsLODs); + int i; + + //walk the lods + for (i=0; iofsEnd; + } + + // avoid the lod pointer data structure + current += sizeof(mdxmLOD_t); + + mdxmLODSurfOffset_t *indexes = (mdxmLODSurfOffset_t *)current; + // we are now looking at the offset array + current += indexes->offsets[index]; + + return (void *)current; +} + +#define SURFACE_SAVE_BLOCK_SIZE sizeof(surfaceInfo_t) +#define BOLT_SAVE_BLOCK_SIZE (sizeof(boltInfo_t) - sizeof(mdxaBone_t)) +#define BONE_SAVE_BLOCK_SIZE sizeof(boneInfo_t) + +void G2_SaveGhoul2Models(CGhoul2Info_v& ghoul2) +{ + ojk::SavedGameHelper saved_game(::ri.saved_game); + + saved_game.reset_buffer(); + + // is there anything to save? + if (!ghoul2.IsValid() || ghoul2.size() == 0) + { + const int zero_size = 0; +#ifdef JK2_MODE + saved_game.write( + zero_size); + + saved_game.write_chunk_and_size( + INT_ID('G', 'L', '2', 'S'), + INT_ID('G', 'H', 'L', '2')); +#else + saved_game.write_chunk(INT_ID('G', 'H', 'L', '2'), zero_size); //write out a zero buffer +#endif // JK2_MODE + + return; + } + + + // save out how many ghoul2 models we have + const int model_count = static_cast(ghoul2.size()); + + saved_game.write(model_count); + + for (int i = 0; i < model_count; ++i) + { + // first save out the ghoul2 details themselves + ghoul2[i].sg_export(saved_game); + + // save out how many surfaces we have + const int surface_count = static_cast(ghoul2[i].mSlist.size()); + saved_game.write(surface_count); + + // now save the all the surface list info + for (int x = 0; x < surface_count; ++x) + { + ghoul2[i].mSlist[x].sg_export( + saved_game); + } + + // save out how many bones we have + const int bone_count = static_cast(ghoul2[i].mBlist.size()); + saved_game.write(bone_count); + + // now save the all the bone list info + for (int x = 0; x < bone_count; ++x) + { + ghoul2[i].mBlist[x].sg_export(saved_game); + } + + // save out how many bolts we have + const int bolt_count = static_cast(ghoul2[i].mBltlist.size()); + saved_game.write(bolt_count); + + // lastly save the all the bolt list info + for (int x = 0; x < bolt_count; ++x) + { + ghoul2[i].mBltlist[x].sg_export(saved_game); + } + } + +#ifdef JK2_MODE + saved_game.write_chunk_and_size( + INT_ID('G', 'L', '2', 'S'), + INT_ID('G', 'H', 'L', '2')); +#else + saved_game.write_chunk( + INT_ID('G', 'H', 'L', '2')); +#endif // JK2_MODE +} + +// have to free space malloced in the save system here because the game DLL can't. +void G2_FreeSaveBuffer(char *buffer) +{ + Z_Free(buffer); +} + +void G2_LoadGhoul2Model( + CGhoul2Info_v& ghoul2, + char* buffer) +{ + static_cast(buffer); + + ojk::SavedGameHelper saved_game(::ri.saved_game); + + // first thing, lets see how many ghoul2 models we have, and resize our buffers accordingly + int model_count = 0; +#ifdef JK2_MODE + if (saved_game.get_buffer_size() > 0) + { +#endif // JK2_MODE + + saved_game.read( + model_count); + +#ifdef JK2_MODE + } +#endif // JK2_MODE + ghoul2.resize(model_count); + + // did we actually resize to a value? + if (model_count == 0) + { + // no, ok, well, done then. + return; + } + + // now we have enough instances, lets go through each one and load up the relevant details + for (decltype(model_count) i = 0; i < model_count; ++i) + { + ghoul2[i].mSkelFrameNum = 0; + ghoul2[i].mModelindex = -1; + ghoul2[i].mFileName[0] = 0; + ghoul2[i].mValid = false; + + // load the ghoul2 info from the buffer + ghoul2[i].sg_import(saved_game); + + if (ghoul2[i].mModelindex != -1 && ghoul2[i].mFileName[0]) + { + ghoul2[i].mModelindex = i; + + ::G2_SetupModelPointers(&ghoul2[i]); + } + + // give us enough surfaces to load up the data + int surface_count = 0; + + saved_game.read(surface_count); + ghoul2[i].mSlist.resize(surface_count); + + // now load all the surfaces + for (decltype(surface_count) x = 0; x < surface_count; ++x) + { + ghoul2[i].mSlist[x].sg_import(saved_game); + } + + // give us enough bones to load up the data + int bone_count = 0; + + saved_game.read(bone_count); + + ghoul2[i].mBlist.resize(bone_count); + + // now load all the bones + for (decltype(bone_count) x = 0; x < bone_count; ++x) + { + ghoul2[i].mBlist[x].sg_import(saved_game); + } + + // give us enough bolts to load up the data + int bolt_count = 0; + + saved_game.read(bolt_count); + + ghoul2[i].mBltlist.resize(bolt_count); + + // now load all the bolts + for (decltype(bolt_count) x = 0; x < bolt_count; ++x) + { + ghoul2[i].mBltlist[x].sg_import(saved_game); + } + } + + saved_game.ensure_all_data_read(); +} + +void G2_LerpAngles(CGhoul2Info_v &ghoul2,CGhoul2Info_v &nextGhoul2, float interpolation) +{ + // loop each model + for (int i=0; i< ghoul2.size(); i++) + { + if (ghoul2[i].mModelindex != -1) + { + // now walk the bone list + for (size_t x = 0; x < ghoul2[i].mBlist.size(); x++) + { + boneInfo_t &bone = ghoul2[i].mBlist[x]; + // sure we have one to lerp to? + if ((nextGhoul2.size() > i) && + (nextGhoul2[i].mModelindex != -1) && + (nextGhoul2[i].mBlist.size() > x) && + (nextGhoul2[i].mBlist[x].boneNumber != -1)) + { + boneInfo_t &nextBone = nextGhoul2[i].mBlist[x]; + // does this bone override actually have anything in it, and if it does, is it a bone angles override? + if ((bone.boneNumber != -1) && ((bone.flags) & (BONE_ANGLES_TOTAL))) + { + float *nowMatrix = (float*) &bone.matrix; + float *nextMatrix = (float*) &nextBone.matrix; + float *newMatrix = (float*) &bone.newMatrix; + // now interpolate the matrix + for (int z=0; z < 12; z++) + { + newMatrix[z] = nowMatrix[z] + interpolation * ( nextMatrix[z] - nowMatrix[z] ); + } + } + } + else + { + memcpy(&ghoul2[i].mBlist[x].newMatrix, &ghoul2[i].mBlist[x].matrix, sizeof(mdxaBone_t)); + } + } + } + } +} diff --git a/code/rd-rend2/G2_surfaces.cpp b/code/rd-rend2/G2_surfaces.cpp new file mode 100644 index 0000000000..1aad99e383 --- /dev/null +++ b/code/rd-rend2/G2_surfaces.cpp @@ -0,0 +1,645 @@ +/* +=========================================================================== +Copyright (C) 2000 - 2013, Raven Software, Inc. +Copyright (C) 2001 - 2013, Activision, Inc. +Copyright (C) 2013 - 2015, OpenJK contributors + +This file is part of the OpenJK source code. + +OpenJK is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License version 2 as +published by the Free Software Foundation. + +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, see . +=========================================================================== +*/ + +#include "server/exe_headers.h" + +#ifndef __Q_SHARED_H + #include "qcommon/q_shared.h" +#endif + +#if !defined(TR_LOCAL_H) + #include "tr_local.h" +#endif + +#if !defined(G2_H_INC) + #include "ghoul2/G2.h" +#endif + +#include "rd-common/tr_types.h" +#include "tr_local.h" +#ifdef _MSC_VER +#pragma warning(disable : 4512) //assignment op could not be genereated +#endif + +#define G2_MODEL_OK(g) ((g)&&(g)->mValid&&(g)->aHeader&&(g)->currentModel&&(g)->animModel) + +class CConstructBoneList +{ +public: + int surfaceNum; + int* boneUsedList; + surfaceInfo_v& rootSList; + model_t* currentModel; + boneInfo_v& boneList; + + CConstructBoneList( + int initsurfaceNum, + int* initboneUsedList, + surfaceInfo_v& initrootSList, + model_t* initcurrentModel, + boneInfo_v& initboneList + ) + : surfaceNum(initsurfaceNum) + , boneUsedList(initboneUsedList) + , rootSList(initrootSList) + , currentModel(initcurrentModel) + , boneList(initboneList) + { } +}; + +class CQuickOverride +{ + int mOverride[512]; + int mAt[512]; + int mCurrentTouch; +public: + CQuickOverride() + { + mCurrentTouch = 1; + memset(mOverride, 0, sizeof(int) * 512); + } + void Invalidate() + { + mCurrentTouch++; + } + void Set(int index, int pos) + { + if (index == 10000) + { + return; + } + assert(index >= 0 && index < 512); + mOverride[index] = mCurrentTouch; + mAt[index] = pos; + } + int Test(int index) + { + assert(index >= 0 && index < 512); + return (mOverride[index] == mCurrentTouch) + ? mAt[index] + : -1; + } +}; + +// functions preferinition +extern void G2_ConstructUsedBoneList(CConstructBoneList &CBL); +extern int G2_DecideTraceLod(CGhoul2Info& ghoul2, int useLod); + +//===================================================================================================================== +// Surface List handling routines - so entities can determine what surfaces attached to a model are operational or not. + +// find a particular surface in the surface override list +static CQuickOverride QuickOverride; + + +const surfaceInfo_t *G2_FindOverrideSurface(int surfaceNum, const surfaceInfo_v &surfaceList) +{ + if (surfaceNum < 0) + { + // starting a new lookup + QuickOverride.Invalidate(); + for (size_t i = 0; i < surfaceList.size(); i++) + { + if (surfaceList[i].surface >= 0) + { + QuickOverride.Set(surfaceList[i].surface, i); + } + } + return NULL; + } + int idx = QuickOverride.Test(surfaceNum); + if (idx < 0) + { + if (surfaceNum == 10000) + { + for (size_t i = 0; i < surfaceList.size(); i++) + { + if (surfaceList[i].surface == surfaceNum) + { + return &surfaceList[i]; + } + } + } +#if _DEBUG + // look through entire list + size_t i; + for (i = 0; i < surfaceList.size(); i++) + { + if (surfaceList[i].surface == surfaceNum) + { + break; + } + } + // didn't find it. + assert(i == surfaceList.size()); // our quickoverride is not working right +#endif + return NULL; + } + assert(idx >= 0 && idx < (int)surfaceList.size()); + assert(surfaceList[idx].surface == surfaceNum); + return &surfaceList[idx]; +} + + +// given a surface name, lets see if it's legal in the model +int G2_IsSurfaceLegal(const model_s* mod_m, const char* surfaceName, uint32_t* flags) +{ + assert(mod_m); + assert(mod_m->data.glm->header); + // damn include file dependancies + mdxmSurfHierarchy_t* surf; + surf = (mdxmSurfHierarchy_t*)((byte*)mod_m->data.glm->header + mod_m->data.glm->header->ofsSurfHierarchy); + + for (int i = 0; i < mod_m->data.glm->header->numSurfaces; i++) + { + if (!Q_stricmp(surfaceName, surf->name)) + { + *flags = surf->flags; + return i; + } + // find the next surface + surf = (mdxmSurfHierarchy_t*)((byte*)surf + (intptr_t)(&((mdxmSurfHierarchy_t*)0)->childIndexes[surf->numChildren])); + } + return -1; +} + + +/************************************************************************************************ + * G2_FindSurface + * find a surface in a ghoul2 surface override list based on it's name + * + * Input + * filename of model, surface list of model instance, name of surface, int to be filled in + * with the index of this surface (defaults to NULL) + * + * Output + * pointer to surface if successful, false otherwise + * + ************************************************************************************************/ +mdxmSurface_t *G2_FindSurface(CGhoul2Info *ghlInfo, surfaceInfo_v &slist, const char *surfaceName, + int *surfIndex/*NULL*/) +{ + int i = 0; + // find the model we want + model_t *mod = (model_t *)ghlInfo->currentModel; + mdxmHierarchyOffsets_t *surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)mod->data.glm->header + sizeof(mdxmHeader_t)); + + // did we find a ghoul 2 model or not? + if (!mod->data.glm || !mod->data.glm->header) + { + assert(0); + if (surfIndex) + { + *surfIndex = -1; + } + return 0; + } + + // first find if we already have this surface in the list + for (i = slist.size() - 1; i >= 0; i--) + { + if ((slist[i].surface != 10000) && (slist[i].surface != -1)) + { + mdxmSurface_t *surf = (mdxmSurface_t *)G2_FindSurface(mod, slist[i].surface, 0); + // back track and get the surfinfo struct for this surface + const mdxmSurfHierarchy_t* surfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surf->thisSurfaceIndex]); + + // are these the droids we're looking for? + if (!Q_stricmp (surfInfo->name, surfaceName)) + { + // yup + if (surfIndex) + { + *surfIndex = i; + } + return surf; + } + } + } + // didn't find it + if (surfIndex) + { + *surfIndex = -1; + } + return 0; +} + +qboolean G2_SetSurfaceOnOff(CGhoul2Info* ghlInfo, surfaceInfo_v& slist, const char* surfaceName, const int offFlags) +{ + int surfIndex = -1; + surfaceInfo_t temp_slist_entry; + + // find the model we want + model_t *mod = (model_t *)ghlInfo->currentModel; + + // did we find a ghoul 2 model or not? + if (!mod->data.glm || !mod->data.glm->header) + { + assert(0); + return qfalse; + } + + // first find if we already have this surface in the list + const mdxmSurface_t* surf = G2_FindSurface(ghlInfo, slist, surfaceName, &surfIndex); + if (surf) + { + // set descendants value + + // slist[surfIndex].offFlags = offFlags; + // seems to me that we shouldn't overwrite the other flags. + // the only bit we really care about in the incoming flags is the off bit + slist[surfIndex].offFlags &= ~(G2SURFACEFLAG_OFF | G2SURFACEFLAG_NODESCENDANTS); + slist[surfIndex].offFlags |= offFlags & (G2SURFACEFLAG_OFF | G2SURFACEFLAG_NODESCENDANTS); + return qtrue; + } + else + { + // ok, not in the list already - in that case, lets verify this surface exists in the model mesh + uint32_t flags; + int surfaceNum = G2_IsSurfaceLegal(mod, surfaceName, &flags); + if (surfaceNum != -1) + { + uint32_t newflags = flags; + // the only bit we really care about in the incoming flags is the off bit + newflags &= ~(G2SURFACEFLAG_OFF | G2SURFACEFLAG_NODESCENDANTS); + newflags |= offFlags & (G2SURFACEFLAG_OFF | G2SURFACEFLAG_NODESCENDANTS); + + if (newflags != flags) + { // insert here then because it changed, no need to add an override otherwise + temp_slist_entry.offFlags = newflags; + temp_slist_entry.surface = surfaceNum; + + slist.push_back(temp_slist_entry); + } + return qtrue; + } + } + return qfalse; +} + +// set a named surface offFlags - if it doesn't find a surface with this name in the list then it will add one. +qboolean G2_SetSurfaceOnOff(CGhoul2Info* ghlInfo, const char* surfaceName, const int offFlags) +{ + return G2_SetSurfaceOnOff(ghlInfo, ghlInfo->mSlist, surfaceName, offFlags); +} + +void G2_SetSurfaceOnOffFromSkin(CGhoul2Info *ghlInfo, qhandle_t renderSkin) +{ + const skin_t *skin = R_GetSkinByHandle( renderSkin ); + + //FIXME: using skin handles means we have to increase the numsurfs in a skin, but reading directly would cause file hits, we need another way to cache or just deal with the larger skin_t + + if (skin) + { + ghlInfo->mSlist.clear(); // remove any overrides we had before. + ghlInfo->mMeshFrameNum = 0; + + for (int j = 0; j < skin->numSurfaces; j++) + { + uint32_t flags; + int surfaceNum = G2_IsSurfaceLegal(ghlInfo->currentModel, skin->surfaces[j]->name, &flags); + + // the names have both been lowercased + if (!(flags & G2SURFACEFLAG_OFF) && !strcmp(((shader_t*)(skin->surfaces[j]->shader))->name, "*off")) + { + G2_SetSurfaceOnOff(ghlInfo, skin->surfaces[j]->name, G2SURFACEFLAG_OFF); + } + else + { + // only turn on if it's not an "_off" surface + if ((surfaceNum != -1) && (!(flags & G2SURFACEFLAG_OFF))) + { + //G2_SetSurfaceOnOff(ghlInfo, skin->surfaces[j]->name, 0); + } + } + } + } +} + +// return a named surfaces off flags - should tell you if this surface is on or off. +/* +int G2_IsSurfaceOff (CGhoul2Info *ghlInfo, surfaceInfo_v &slist, const char *surfaceName) +{ + model_t *mod = (model_t *)ghlInfo->currentModel; + int surfIndex = -1; + mdxmSurface_t *surf = 0; + mdxmHeader_t *mdxm = mod->data.glm->header; + + // did we find a ghoul 2 model or not? + if (!mdxm) + { + return 0; + } + + // first find if we already have this surface in the list + surf = G2_FindSurface(ghlInfo, slist, surfaceName, &surfIndex); + if (surf) + { + // set descendants value + return slist[surfIndex].offFlags; + } + // ok, we didn't find it in the surface list. Lets look at the original surface then. + + mdxmSurfHierarchy_t *surface = (mdxmSurfHierarchy_t *) ( (byte *)mdxm + mdxm->ofsSurfHierarchy ); + + for ( int i = 0 ; i < mdxm->numSurfaces ; i++) + { + if (!Q_stricmp(surfaceName, surface->name)) + { + return surface->flags; + } + // find the next surface + surface = (mdxmSurfHierarchy_t *)( (byte *)surface + (intptr_t)( &((mdxmSurfHierarchy_t *)0)->childIndexes[ surface->numChildren ] )); + } + + assert(0); + return 0; +} +*/ + +void G2_FindRecursiveSurface(const model_t* currentModel, int surfaceNum, surfaceInfo_v& rootList, int* activeSurfaces) +{ + assert(currentModel); + assert(currentModel->data.glm); + int i; + mdxmSurface_t *surface = (mdxmSurface_t *)G2_FindSurface(currentModel, surfaceNum, 0); + mdxmHierarchyOffsets_t *surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)currentModel->data.glm->header + sizeof(mdxmHeader_t)); + mdxmSurfHierarchy_t *surfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surface->thisSurfaceIndex]); + + // see if we have an override surface in the surface list + const surfaceInfo_t *surfOverride = G2_FindOverrideSurface(surfaceNum, rootList); + + // really, we should use the default flags for this surface unless it's been overriden + int offFlags = surfInfo->flags; + + // set the off flags if we have some + if (surfOverride) + { + offFlags = surfOverride->offFlags; + } + + // if this surface is not off, indicate as such in the active surface list + if (!(offFlags & G2SURFACEFLAG_OFF)) + { + activeSurfaces[surfaceNum] = 1; + } + else + // if we are turning off all descendants, then stop this recursion now + if (offFlags & G2SURFACEFLAG_NODESCENDANTS) + { + return; + } + + // now recursively call for the children + for (i=0; i< surfInfo->numChildren; i++) + { + surfaceNum = surfInfo->childIndexes[i]; + G2_FindRecursiveSurface(currentModel, surfaceNum, rootList, activeSurfaces); + } + +} + +void G2_RemoveRedundantGeneratedSurfaces(surfaceInfo_v &slist, int *activeSurfaces) +{ + // walk the surface list, removing surface overrides or generated surfaces that are pointing at surfaces that aren't active anymore + for (size_t i=0; i= 0 && modelIndex < ghoul2.size()); + assert(ghoul2[modelIndex].currentModel && ghoul2[modelIndex].animModel); + + model_t *mod_m = (model_t *)ghoul2[modelIndex].currentModel; + model_t *mod_a = (model_t *)ghoul2[modelIndex].animModel; + mdxmHeader_t *mdxm = mod_m->data.glm->header; + mdxaHeader_t *mdxa = mod_a->data.gla; + + // did we find a ghoul 2 model or not? + if (!mdxm) + { + return qfalse; + } + + // first find if we already have this surface in the list + surf = G2_IsSurfaceLegal(mod_m, surfaceName, &flags); + if (surf != -1) + { + // set the root surface + ghoul2[modelIndex].mSurfaceRoot = surf; + + return qtrue; + } + assert(0); + return qfalse; +} + + +int G2_AddSurface(CGhoul2Info *ghoul2, int surfaceNumber, int polyNumber, float BarycentricI, float BarycentricJ, int lod ) +{ + + surfaceInfo_t temp_slist_entry; + + // decide if LOD is legal + lod = G2_DecideTraceLod(*ghoul2, lod); + + // first up, see if we have a free one already set up - look only from the end of the constant surfaces onwards + size_t i; + for (i=0; imSlist.size(); i++) + { + // is the surface count -1? That would indicate it's free + if (ghoul2->mSlist[i].surface == -1) + { + break; + } + } + + if (i == ghoul2->mSlist.size()) + { + ghoul2->mSlist.push_back(surfaceInfo_t()); + } + + ghoul2->mSlist[i].offFlags = G2SURFACEFLAG_GENERATED; + ghoul2->mSlist[i].surface = 10000; // no model will ever have 10000 surfaces + ghoul2->mSlist[i].genBarycentricI = BarycentricI; + ghoul2->mSlist[i].genBarycentricJ = BarycentricJ; + ghoul2->mSlist[i].genPolySurfaceIndex = ((polyNumber & 0xffff) << 16) | (surfaceNumber & 0xffff); + ghoul2->mSlist[i].genLod = lod; + + return i; +} + +qboolean G2_RemoveSurface(surfaceInfo_v &slist, const int index) +{ + // did we find it? + if (index != -1) + { + // set us to be the 'not active' state + slist[index].surface = -1; + + unsigned int newSize = slist.size(); + // now look through the list from the back and see if there is a block of -1's we can resize off the end of the list + for (int i=slist.size()-1; i>-1; i--) + { + if (slist[i].surface == -1) + { + newSize = i; + } + // once we hit one that isn't a -1, we are done. + else + { + break; + } + } + // do we need to resize? + if (newSize != slist.size()) + { + // yes, so lets do it + slist.resize(newSize); + } + + return qtrue; + } + + assert(0); + + // no + return qfalse; +} + + +int G2_GetParentSurface(CGhoul2Info *ghlInfo, const int index) +{ + model_t *mod = (model_t *)ghlInfo->currentModel; + mdxmSurface_t *surf = 0; + mdxmHierarchyOffsets_t *surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)mod->data.glm->header + sizeof(mdxmHeader_t)); + mdxmSurfHierarchy_t *surfInfo = 0; + + // walk each surface and see if this index is listed in it's children + surf = (mdxmSurface_t *)G2_FindSurface(mod, index, 0); + surfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surf->thisSurfaceIndex]); + + return surfInfo->parentIndex; + +} + +int G2_GetSurfaceIndex(CGhoul2Info *ghlInfo, const char *surfaceName) +{ + model_t *mod = (model_t *)ghlInfo->currentModel; + uint32_t flags; + + return G2_IsSurfaceLegal(mod, surfaceName, &flags); +} + +int G2_IsSurfaceRendered(CGhoul2Info *ghlInfo, const char *surfaceName, surfaceInfo_v &slist) +{ + uint32_t flags = 0;//, surfFlags = 0; + int surfIndex = 0; + assert(ghlInfo->currentModel); + assert(ghlInfo->currentModel->data.glm && ghlInfo->currentModel->data.glm->header); + if (!ghlInfo->currentModel->data.glm || !ghlInfo->currentModel->data.glm->header) + { + return -1; + } + + // now travel up the skeleton to see if any of it's ancestors have a 'no descendants' turned on + + // find the original surface in the surface list + int surfNum = G2_IsSurfaceLegal((model_t *)ghlInfo->currentModel, surfaceName, &flags); + if ( surfNum != -1 ) + {//must be legal + const mdxmHierarchyOffsets_t *surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)ghlInfo->currentModel->data.glm->header + sizeof(mdxmHeader_t)); + const mdxmSurfHierarchy_t *surfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surfNum]); + surfNum = surfInfo->parentIndex; + // walk the surface hierarchy up until we hit the root + while (surfNum != -1) + { + const mdxmSurface_t* parentSurf; + uint32_t parentFlags; + const mdxmSurfHierarchy_t* parentSurfInfo; + + parentSurfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surfNum]); + + // find the original surface in the surface list + //G2 was bug, above comment was accurate, but we don't want the original flags, we want the parent flags + G2_IsSurfaceLegal((model_t *)ghlInfo->currentModel, parentSurfInfo->name, &parentFlags); + + // now see if we already have overriden this surface in the slist + parentSurf = G2_FindSurface(ghlInfo, slist, parentSurfInfo->name, &surfIndex); + if (parentSurf) + { + // set descendants value + parentFlags = slist[surfIndex].offFlags; + } + // now we have the parent flags, lets see if any have the 'no descendants' flag set + if (parentFlags & G2SURFACEFLAG_NODESCENDANTS) + { + flags |= G2SURFACEFLAG_OFF; + break; + } + // set up scan of next parent + surfNum = parentSurfInfo->parentIndex; + } + } + else + { + return -1; + } + if ( flags == 0 ) + {//it's not being overridden by a parent + // now see if we already have overriden this surface in the slist + const mdxmSurface_t *surf = G2_FindSurface(ghlInfo, slist, surfaceName, &surfIndex); + if (surf) + { + // set descendants value + flags = slist[surfIndex].offFlags; + } + // ok, at this point in flags we have what this surface is set to, and the index of the surface itself + } + return flags; +} diff --git a/code/rd-rend2/tr_draw.cpp b/code/rd-rend2/tr_draw.cpp new file mode 100644 index 0000000000..89f40b813b --- /dev/null +++ b/code/rd-rend2/tr_draw.cpp @@ -0,0 +1,847 @@ +/* +=========================================================================== +Copyright (C) 1999 - 2005, Id Software, Inc. +Copyright (C) 2000 - 2013, Raven Software, Inc. +Copyright (C) 2001 - 2013, Activision, Inc. +Copyright (C) 2005 - 2015, ioquake3 contributors +Copyright (C) 2013 - 2015, OpenJK contributors + +This file is part of the OpenJK source code. + +OpenJK is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License version 2 as +published by the Free Software Foundation. + +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, see . +=========================================================================== +*/ + +// tr_draw.c +#include "tr_local.h" + +void RE_GetScreenShot(byte *buffer, int w, int h) +{ + byte *source, *allsource; + byte *src, *dst; + size_t offset = 0, memcount; + int padlen; + + int x, y; + int r, g, b; + float xScale, yScale; + int xx, yy; + + allsource = RB_ReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, &offset, &padlen); + source = allsource + offset; + + memcount = (glConfig.vidWidth * 3 + padlen) * glConfig.vidHeight; + + // resample from source + xScale = glConfig.vidWidth / (4.0*w); + yScale = glConfig.vidHeight / (3.0*h); + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + r = g = b = 0; + for (yy = 0; yy < 3; yy++) { + for (xx = 0; xx < 4; xx++) { + src = source + 3 * (glConfig.vidWidth * (int)((y * 3 + yy)*yScale) + (int)((x * 4 + xx)*xScale)); + r += src[0]; + g += src[1]; + b += src[2]; + } + } + dst = buffer + 4 * (h * w - y * w + x); + dst[0] = r / 12; + dst[1] = g / 12; + dst[2] = b / 12; + } + } + + // gamma correct + if (glConfig.deviceSupportsGamma) + R_GammaCorrect(buffer, w * h * 4); + + Hunk_FreeTempMemory(allsource); +} + +// this is just a chunk of code from RE_TempRawImage_ReadFromFile() below, subroutinised so I can call it +// from the screen dissolve code as well... +// +static byte *RE_ReSample(byte *pbLoadedPic, int iLoadedWidth, int iLoadedHeight, + byte *pbReSampleBuffer, int *piWidth, int *piHeight + ) +{ + byte *pbReturn = NULL; + + // if not resampling, just return some values and return... + // + if ( pbReSampleBuffer == NULL || (iLoadedWidth == *piWidth && iLoadedHeight == *piHeight) ) + { + // if not resampling, we're done, just return the loaded size... + // + *piWidth = iLoadedWidth; + *piHeight= iLoadedHeight; + pbReturn = pbLoadedPic; + } + else + { + // resample from pbLoadedPic to pbReSampledBuffer... + // + float fXStep = (float)iLoadedWidth / (float)*piWidth; + float fYStep = (float)iLoadedHeight/ (float)*piHeight; + int iTotPixelsPerDownSample = (int)ceil(fXStep) * (int)ceil(fYStep); + + int r,g,b; + + byte *pbDst = pbReSampleBuffer; + + for ( int y=0; y<*piHeight; y++ ) + { + for ( int x=0; x<*piWidth; x++ ) + { + r=g=b=0; + + for ( float yy = (float)y*fYStep; yy < (float)(y+1)*fYStep ; yy+=1 ) + { + for ( float xx = (float)x*fXStep; xx < (float)(x+1)*fXStep ; xx+=1 ) + { + byte *pbSrc = pbLoadedPic + 4 * ( ((int)yy * iLoadedWidth) + (int)xx ); + + assert(pbSrc < pbLoadedPic + (iLoadedWidth * iLoadedHeight * 4) ); + + r += pbSrc[0]; + g += pbSrc[1]; + b += pbSrc[2]; + } + } + + assert(pbDst < pbReSampleBuffer + (*piWidth * *piHeight * 4)); + + pbDst[0] = r / iTotPixelsPerDownSample; + pbDst[1] = g / iTotPixelsPerDownSample; + pbDst[2] = b / iTotPixelsPerDownSample; + pbDst[3] = 255; + pbDst += 4; + } + } + + // set return value... + // + pbReturn = pbReSampleBuffer; + } + + return pbReturn; +} + + +// this is so the server (or anyone else) can get access to raw pixels if they really need to, +// currently it's only used by the server so that savegames can embed a graphic in the auto-save files +// (which can't do a screenshot since they're saved out before the level is drawn). +// +// by default, the pic will be returned as the original dims, but if pbReSampleBuffer != NULL then it's assumed to +// be a big enough buffer to hold the resampled image, which also means that the width and height params are read as +// inputs (as well as still being inherently outputs) and the pic is scaled to that size, and to that buffer. +// +// the return value is either NULL, or a pointer to the pixels to use (which may be either the pbReSampleBuffer param, +// or the local ptr below). +// +// In either case, you MUST call the free-up function afterwards ( RE_TempRawImage_CleanUp() ) to get rid of any temp +// memory after you've finished with the pic. +// +// Note: ALWAYS use the return value if != NULL, even if you passed in a declared resample buffer. This is because the +// resample will get skipped if the values you want are the same size as the pic that it loaded, so it'll return a +// different buffer. +// +// the vertflip param is used for those functions that expect things in OpenGL's upside-down pixel-read format (sigh) +// +// (not brilliantly fast, but it's only used for weird stuff anyway) +// +byte* pbLoadedPic = NULL; + +byte* RE_TempRawImage_ReadFromFile(const char *psLocalFilename, int *piWidth, int *piHeight, byte *pbReSampleBuffer, qboolean qbVertFlip) +{ + RE_TempRawImage_CleanUp(); // jic + + byte *pbReturn = NULL; + + if (psLocalFilename && piWidth && piHeight) + { + int iLoadedWidth, iLoadedHeight; + + R_LoadImage( psLocalFilename, &pbLoadedPic, &iLoadedWidth, &iLoadedHeight); + if ( pbLoadedPic ) + { + pbReturn = RE_ReSample( pbLoadedPic, iLoadedWidth, iLoadedHeight, + pbReSampleBuffer, piWidth, piHeight); + } + } + + if (pbReturn && qbVertFlip) + { + unsigned int *pSrcLine = (unsigned int *) pbReturn; + unsigned int *pDstLine = (unsigned int *) pbReturn + (*piHeight * *piWidth ); // *4 done by compiler (longs) + pDstLine-= *piWidth; // point at start of last line, not first after buffer + + for (int iLineCount=0; iLineCount<*piHeight/2; iLineCount++) + { + for (int x=0; x<*piWidth; x++) + { + unsigned int l = pSrcLine[x]; + pSrcLine[x] = pDstLine[x]; + pDstLine[x] = l; + } + pSrcLine += *piWidth; + pDstLine -= *piWidth; + } + } + + return pbReturn; +} + +void RE_TempRawImage_CleanUp(void) +{ + if ( pbLoadedPic ) + { + R_Free( pbLoadedPic ); + pbLoadedPic = NULL; + } +} + +#ifdef REND2_SP +typedef enum +{ + eDISSOLVE_RT_TO_LT = 0, + eDISSOLVE_LT_TO_RT, + eDISSOLVE_TP_TO_BT, + eDISSOLVE_BT_TO_TP, + eDISSOLVE_CIRCULAR_OUT, // new image comes out from centre + // + eDISSOLVE_RAND_LIMIT, // label only, not valid to select + // + // any others... + // + eDISSOLVE_CIRCULAR_IN, // new image comes in from edges + // + eDISSOLVE_NUMBEROF + +} Dissolve_e; + +typedef struct +{ + int iWidth; + int iHeight; + int iUploadWidth; + int iUploadHeight; + int iScratchPadNumber; + image_t *pImage; // old image screen + image_t *pDissolve; // fuzzy thing + image_t *pBlack; // small black image for clearing + int iStartTime; // 0 = not processing + Dissolve_e eDissolveType; + qboolean bTouchNeeded; + +} Dissolve_t; + +static int PowerOf2(int iArg) +{ + if ( (iArg & (iArg-1)) != 0) + { + int iShift=0; + while (iArg) + { + iArg>>=1; + iShift++; + } + + iArg = 1<width)*(float)iDissolvePercentage)/100.0f); + + // blit the fuzzy-dissolve sprite... + // + x0 = fXScaleFactor * fXboundary; + y0 = 0.0f; + x1 = fXScaleFactor * (fXboundary + Dissolve.pDissolve->width); + y1 = 0.0f; + x2 = x1; + y2 = fYScaleFactor * Dissolve.iHeight; + x3 = x0; + y3 = y2; + + RE_Blit(x0,y0,x1,y1,x2,y2,x3,y3, Dissolve.pDissolve, GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE, true); + + // blit a blank thing over the area the old screen is to be displayed on to enable screen-writing... + // (to the left of fXboundary) + // + x0 = 0.0f; + y0 = 0.0f; + x1 = fXScaleFactor * (fXboundary + iSAFETY_SPRITE_OVERLAP); + y1 = 0.0f; + x2 = x1; + y2 = fYScaleFactor * Dissolve.iHeight; + x3 = x0; + y3 = y2; + RE_Blit(x0,y0,x1,y1,x2,y2,x3,y3, Dissolve.pBlack, GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE, false); + } + break; + + case eDISSOLVE_LT_TO_RT: + { + float fXboundary = (((float)(Dissolve.iWidth+(2*Dissolve.pDissolve->width))*(float)iDissolvePercentage)/100.0f) - Dissolve.pDissolve->width; + + // blit the fuzzy-dissolve sprite... + // + x0 = fXScaleFactor * (fXboundary + Dissolve.pDissolve->width); + y0 = 0.0f; + x1 = fXScaleFactor * fXboundary; + y1 = 0.0f; + x2 = x1; + y2 = fYScaleFactor * Dissolve.iHeight; + x3 = x0; + y3 = y2; + + RE_Blit(x0,y0,x1,y1,x2,y2,x3,y3, Dissolve.pDissolve, GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE, true); + + // blit a blank thing over the area the old screen is to be displayed on to enable screen-writing... + // (to the right of fXboundary) + // + x0 = fXScaleFactor * (( fXboundary + Dissolve.pDissolve->width) - iSAFETY_SPRITE_OVERLAP); + y0 = 0.0f; + x1 = fXScaleFactor * Dissolve.iWidth; + y0 = 0.0f; + x2 = x1; + y2 = fYScaleFactor * Dissolve.iHeight; + x3 = x0; + y3 = y2; + RE_Blit(x0,y0,x1,y1,x2,y2,x3,y3, Dissolve.pBlack, GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE, false); + } + break; + + case eDISSOLVE_TP_TO_BT: + { + float fYboundary = (((float)(Dissolve.iHeight+(2*Dissolve.pDissolve->width))*(float)iDissolvePercentage)/100.0f) - Dissolve.pDissolve->width; + + // blit the fuzzy-dissolve sprite... + // + x0 = 0.0f; + y0 = fYScaleFactor * (fYboundary + Dissolve.pDissolve->width); + x1 = x0; + y1 = fYScaleFactor * fYboundary; + x2 = fXScaleFactor * Dissolve.iWidth; + y2 = y1; + x3 = x2; + y3 = y0; + + RE_Blit(x0,y0,x1,y1,x2,y2,x3,y3, Dissolve.pDissolve, GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE, true); + + // blit a blank thing over the area the old screen is to be displayed on to enable screen-writing... + // (underneath fYboundary) + // + x0 = 0.0f; + y0 = fYScaleFactor * ( (fYboundary + Dissolve.pDissolve->width) - iSAFETY_SPRITE_OVERLAP); + x1 = fXScaleFactor * Dissolve.iWidth; + y1 = y0; + x2 = x1; + y2 = fYScaleFactor * Dissolve.iHeight; + x3 = x0; + y3 = y2; + RE_Blit(x0,y0,x1,y1,x2,y2,x3,y3, Dissolve.pBlack, GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE, false); + } + break; + + case eDISSOLVE_BT_TO_TP: + { + float fYboundary = Dissolve.iHeight - (((float)(Dissolve.iHeight+Dissolve.pDissolve->width)*(float)iDissolvePercentage)/100.0f); + + // blit the fuzzy-dissolve sprite... + // + x0 = 0.0f; + y0 = fYScaleFactor * fYboundary; + x1 = x0; + y1 = fYScaleFactor * (fYboundary + Dissolve.pDissolve->width); + x2 = fXScaleFactor * Dissolve.iWidth; + y2 = y1; + x3 = x2; + y3 = y0; + + RE_Blit(x0,y0,x1,y1,x2,y2,x3,y3, Dissolve.pDissolve, GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE, true); + + // blit a blank thing over the area the old screen is to be displayed on to enable screen-writing... + // (above fYboundary) + // + x0 = 0.0f; + y0 = 0.0f; + x1 = fXScaleFactor * Dissolve.iWidth; + y1 = y0; + x2 = x1; + y2 = fYScaleFactor * (fYboundary + iSAFETY_SPRITE_OVERLAP); + x3 = x0; + y3 = y2; + RE_Blit(x0,y0,x1,y1,x2,y2,x3,y3, Dissolve.pBlack, GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE, false); + } + break; + + case eDISSOLVE_CIRCULAR_IN: + { + float fDiagZoom = ( ((float)Dissolve.iWidth*0.8) * (100-iDissolvePercentage))/100.0f; + + // + // blit circular graphic... + // + x0 = fXScaleFactor * ((Dissolve.iWidth/2) - fDiagZoom); + y0 = fYScaleFactor * ((Dissolve.iHeight/2)- fDiagZoom); + x1 = fXScaleFactor * ((Dissolve.iWidth/2) + fDiagZoom); + y1 = y0; + x2 = x1; + y2 = fYScaleFactor * ((Dissolve.iHeight/2)+ fDiagZoom); + x3 = x0; + y3 = y2; + + RE_Blit(x0,y0,x1,y1,x2,y2,x3,y3, Dissolve.pDissolve, GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE, true); + } + break; + + case eDISSOLVE_CIRCULAR_OUT: + { + float fDiagZoom = ( ((float)Dissolve.iWidth*0.8) * iDissolvePercentage)/100.0f; + + // + // blit circular graphic... + // + x0 = fXScaleFactor * ((Dissolve.iWidth/2) - fDiagZoom); + y0 = fYScaleFactor * ((Dissolve.iHeight/2)- fDiagZoom); + x1 = fXScaleFactor * ((Dissolve.iWidth/2) + fDiagZoom); + y1 = y0; + x2 = x1; + y2 = fYScaleFactor * ((Dissolve.iHeight/2)+ fDiagZoom); + x3 = x0; + y3 = y2; + + RE_Blit(x0,y0,x1,y1,x2,y2,x3,y3, Dissolve.pDissolve, GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE, true); + // now blit the 4 black squares around it to mask off the rest of the screen... + // + // LHS, top to bottom... + // + RE_Blit(0,0, // x0,y0 + x0+iSAFETY_SPRITE_OVERLAP,0, // x1,y1 + x0+iSAFETY_SPRITE_OVERLAP,(fYScaleFactor * Dissolve.iHeight),// x2,y2 + 0,(fYScaleFactor * Dissolve.iHeight), // x3,y3, + Dissolve.pBlack, GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE, + false + ); + + // RHS top to bottom... + // + RE_Blit(x1-iSAFETY_SPRITE_OVERLAP,0, // x0,y0 + (fXScaleFactor * Dissolve.iWidth),0, // x1,y1 + (fXScaleFactor * Dissolve.iWidth),(fYScaleFactor * Dissolve.iHeight),// x2,y2 + x1-iSAFETY_SPRITE_OVERLAP,(fYScaleFactor * Dissolve.iHeight), // x3,y3, + Dissolve.pBlack, GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE, + false + ); + + // top... + // + RE_Blit(x0-iSAFETY_SPRITE_OVERLAP,0, // x0,y0 + x1+iSAFETY_SPRITE_OVERLAP,0, // x1,y1 + x1+iSAFETY_SPRITE_OVERLAP,y0 + iSAFETY_SPRITE_OVERLAP, // x2,y2 + x0-iSAFETY_SPRITE_OVERLAP,y0 + iSAFETY_SPRITE_OVERLAP, // x3,y3 + Dissolve.pBlack, GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE, + false + ); + + // bottom... + // + RE_Blit(x0-iSAFETY_SPRITE_OVERLAP,y3-iSAFETY_SPRITE_OVERLAP, // x0,y0 + x1+iSAFETY_SPRITE_OVERLAP,y2-iSAFETY_SPRITE_OVERLAP, // x1,y1 + x1+iSAFETY_SPRITE_OVERLAP,(fYScaleFactor * Dissolve.iHeight), // x2,y2 + x0-iSAFETY_SPRITE_OVERLAP,(fYScaleFactor * Dissolve.iHeight), // x3,y3 + Dissolve.pBlack, GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_ZERO | GLS_DSTBLEND_ONE, + false + ); + } + break; + + default: + { + assert(0); + iDissolvePercentage = 101; // force a dissolve-kill + break; + } + } + + // re-check in case we hit the default case above... + // + if (iDissolvePercentage <= 100) + { + // still dissolving, so now (finally), blit old image over top... + // + x0 = 0.0f; + y0 = 0.0f; + x1 = fXScaleFactor * Dissolve.pImage->width; + y1 = y0; + x2 = x1; + y2 = fYScaleFactor * Dissolve.pImage->height; + x3 = x0; + y3 = y2; + + RE_Blit(x0,y0,x1,y1,x2,y2,x3,y3, Dissolve.pImage, GLS_DEPTHFUNC_EQUAL, false); + } + } + + if (iDissolvePercentage > 100) + { + RE_KillDissolve(); + } + } + + return qfalse; +} + +// return = qtrue(success) else fail, for those interested... +// +qboolean RE_InitDissolve(qboolean bForceCircularExtroWipe) +{ + R_IssuePendingRenderCommands(); + +// ri.Printf( PRINT_ALL, "RE_InitDissolve()\n"); + qboolean bReturn = qfalse; + + if (//Dissolve.iStartTime == 0 // no point in interruping an existing one + //&& + tr.registered == qtrue // ... stops it crashing during first cinematic before the menus... :-) + ) + { + RE_KillDissolve(); // kill any that are already running + + int iPow2VidWidth = PowerOf2( glConfig.vidWidth ); + int iPow2VidHeight = PowerOf2( glConfig.vidHeight); + + int iBufferBytes = iPow2VidWidth * iPow2VidHeight * 4; + byte *pBuffer = (byte *) R_Malloc( iBufferBytes, TAG_TEMP_WORKSPACE, qfalse); + if (pBuffer) + { + // read current screen image... (GL_RGBA should work even on 3DFX in that the RGB parts will be valid at least) + // + qglReadPixels (0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_RGBA, GL_UNSIGNED_BYTE, pBuffer ); + // + // now expand the pic over the top of itself so that it has a stride value of {PowerOf2(glConfig.vidWidth)} + // (for GL power-of-2 rules) + // + byte *pbSrc = &pBuffer[ glConfig.vidWidth * glConfig.vidHeight * 4]; + byte *pbDst = &pBuffer[ iPow2VidWidth * glConfig.vidHeight * 4]; + // + // ( clear to end, since we've got pbDst nicely setup here) + // + int iClearBytes = &pBuffer[iBufferBytes] - pbDst; + memset(pbDst, 0, iClearBytes); + // + // work out copy/stride vals... + // + iClearBytes = ( iPow2VidWidth - glConfig.vidWidth ) * 4; + int iCopyBytes = glConfig.vidWidth * 4; + // + // do it... + // + for (int y = 0; y < glConfig.vidHeight; y++) + { + pbDst -= iClearBytes; + memset(pbDst,0,iClearBytes); + pbDst -= iCopyBytes; + pbSrc -= iCopyBytes; + memmove(pbDst, pbSrc, iCopyBytes); + } + // + // ok, now we've got the screen image in the top left of the power-of-2 texture square, + // but of course the damn thing's upside down (thanks, GL), so invert it, but only within + // the picture pixels, NOT the upload texture as a whole... + // + byte *pbSwapLineBuffer = (byte *)R_Malloc( iCopyBytes, TAG_TEMP_WORKSPACE, qfalse); + pbSrc = &pBuffer[0]; + pbDst = &pBuffer[(glConfig.vidHeight-1) * iPow2VidWidth * 4]; + for (int y = 0; y < glConfig.vidHeight/2; y++) + { + memcpy(pbSwapLineBuffer, pbDst, iCopyBytes); + memcpy(pbDst, pbSrc, iCopyBytes); + memcpy(pbSrc, pbSwapLineBuffer, iCopyBytes); + pbDst -= iPow2VidWidth*4; + pbSrc += iPow2VidWidth*4; + } + R_Free(pbSwapLineBuffer); + + // + // Now, in case of busted drivers, 3DFX cards, etc etc we stomp the alphas to 255... + // + byte *pPix = pBuffer; + for (int i=0; i iTexSize) { + Dissolve.iUploadWidth = iTexSize; + } + + if (Dissolve.iUploadHeight > iTexSize) { + Dissolve.iUploadHeight = iTexSize; + } + + // alloc resample buffer... (note slight optimisation to avoid spurious alloc) + // + byte *pbReSampleBuffer = ( iPow2VidWidth == Dissolve.iUploadWidth && + iPow2VidHeight == Dissolve.iUploadHeight + )? + NULL : + (byte*) R_Malloc( iPow2VidWidth * iPow2VidHeight * 4, TAG_TEMP_WORKSPACE, qfalse); + + // re-sample screen... + // + byte *pbScreenSprite = RE_ReSample( pBuffer, // byte *pbLoadedPic + iPow2VidWidth, // int iLoadedWidth + iPow2VidHeight, // int iLoadedHeight + // + pbReSampleBuffer, // byte *pbReSampleBuffer + &Dissolve.iUploadWidth, // int *piWidth + &Dissolve.iUploadHeight // int *piHeight + ); + + Dissolve.pImage = R_CreateImage("*DissolveImage", // const char *name + pbScreenSprite, // const byte *pic + Dissolve.iUploadWidth, // int width + Dissolve.iUploadHeight, // int height + IMGTYPE_COLORALPHA, + IMGFLAG_CLAMPTOEDGE, + GL_RGBA8); + + + static byte bBlack[8*8*4]={0}; + for (int j=0; j<8*8*4; j+=4) // itu? + bBlack[j+3]=255; // + + Dissolve.pBlack = R_CreateImage("*DissolveBlack", // const char *name + bBlack, // const byte *pic + 8, // int width + 8, // int height + IMGTYPE_COLORALPHA, + IMGFLAG_CLAMPTOEDGE, + GL_RGBA8); + + if (pbReSampleBuffer) + { + R_Free(pbReSampleBuffer); + } + R_Free(pBuffer); + + // pick dissolve type... + // +#if 0 + // cycles through every dissolve type, for testing... + // + static Dissolve_e eDissolve = (Dissolve_e) 0; + Dissolve.eDissolveType = eDissolve; + eDissolve = (Dissolve_e) (eDissolve+1); + if (eDissolve == eDISSOLVE_RAND_LIMIT) + eDissolve = (Dissolve_e) (eDissolve+1); + if (eDissolve >= eDISSOLVE_NUMBEROF) + eDissolve = (Dissolve_e) 0; +#else + // final (& random) version... + // + Dissolve.eDissolveType = (Dissolve_e) Q_irand( 0, eDISSOLVE_RAND_LIMIT-1); +#endif + + if (bForceCircularExtroWipe) + { + Dissolve.eDissolveType = eDISSOLVE_CIRCULAR_IN; + } + + // ... and load appropriate graphics... + // + + // special tweak, although this code is normally called just before client spawns into world (and + // is therefore pretty much immune to precache issues) I also need to make sure that the inverse + // iris graphic is loaded so for the special case of doing a circular wipe at the end of the last + // level doesn't stall on loading the image. So I'll load it here anyway - to prime the image - + // then allow the random wiper to overwrite the ptr if needed. This way the end of level call + // will be instant. Downside: every level has one extra 256x256 texture. + // Trying to decipher these comments - looks like no problem taking this out. I want the RAM. + imgType_t type = IMGTYPE_COLORALPHA; + int flags = IMGFLAG_CLAMPTOEDGE; + { + Dissolve.pDissolve = R_FindImageFile("gfx/2d/iris_mono_rev", type, flags); + } + + extern cvar_t *com_buildScript; + if (com_buildScript->integer) + { + // register any/all of the possible CASE statements below... + // + + Dissolve.pDissolve = R_FindImageFile( "gfx/2d/iris_mono", type, flags); + Dissolve.pDissolve = R_FindImageFile( "textures/common/dissolve", type, flags); + } + + switch (Dissolve.eDissolveType) + { + case eDISSOLVE_CIRCULAR_IN: + { + Dissolve.pDissolve = R_FindImageFile( "gfx/2d/iris_mono_rev", type, flags); + } + break; + + case eDISSOLVE_CIRCULAR_OUT: + { + Dissolve.pDissolve = R_FindImageFile( "gfx/2d/iris_mono", type, flags); + } + break; + + default: + { + Dissolve.pDissolve = R_FindImageFile( "textures/common/dissolve", type, IMGFLAG_NONE); + } + break; + } + + // all good?... + // + if (Dissolve.pDissolve) // test if image was found, if not, don't do dissolves + { + Dissolve.iStartTime = ri.Milliseconds(); // gets overwritten first time, but MUST be set to NZ + Dissolve.bTouchNeeded = qtrue; + bReturn = qtrue; + } + else + { + RE_KillDissolve(); + } + } + } + + return bReturn; +} +#endif \ No newline at end of file diff --git a/code/rd-rend2/tr_init.cpp b/code/rd-rend2/tr_init.cpp new file mode 100644 index 0000000000..6e30c52bc9 --- /dev/null +++ b/code/rd-rend2/tr_init.cpp @@ -0,0 +1,2507 @@ +/* +=========================================================================== +Copyright (C) 1999-2005 Id Software, Inc. + +This file is part of Quake III Arena source code. + +Quake III Arena source code is free software; you can redistribute it +and/or modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the License, +or (at your option) any later version. + +Quake III Arena source code 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 Quake III Arena source code; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +=========================================================================== +*/ +// tr_init.c -- functions that are not called every frame + +#include "tr_local.h" +//#include "tr_stl.h" +//#include "ghoul2/g2_local.h" +#include "tr_cache.h" +#include "tr_allocator.h" +#include "tr_weather.h" +#include + +#ifdef _G2_GORE +#include "G2_gore_r2.h" +#endif + +static size_t STATIC_UNIFORM_BUFFER_SIZE = 1 * 1024 * 1024; +static size_t FRAME_UNIFORM_BUFFER_SIZE = 8*1024*1024; +static size_t FRAME_SCENE_UNIFORM_BUFFER_SIZE = 1 * 1024 * 1024; +static size_t FRAME_VERTEX_BUFFER_SIZE = 12*1024*1024; +static size_t FRAME_INDEX_BUFFER_SIZE = 4*1024*1024; + +#if defined(_WIN32) +extern "C" { + __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; + __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; +} +#endif + +glconfig_t glConfig; +glconfigExt_t glConfigExt; +glRefConfig_t glRefConfig; +glstate_t glState; +window_t window; + +cvar_t *se_language; +#ifdef JK2_MODE +cvar_t *sp_language; // JK2 +#endif + +cvar_t *r_verbose; +cvar_t *r_ignore; + +cvar_t *r_detailTextures; + +cvar_t *r_znear; +cvar_t *r_zproj; +cvar_t *r_stereoSeparation; + +cvar_t *r_skipBackEnd; + +cvar_t *r_stereo; +cvar_t *r_anaglyphMode; + +cvar_t *r_greyscale; + +cvar_t *r_measureOverdraw; + +cvar_t *r_inGameVideo; +cvar_t *r_fastsky; +cvar_t *r_drawSun; +cvar_t *r_dynamiclight; + +cvar_t *r_lodbias; +cvar_t *r_lodscale; +cvar_t *r_autolodscalevalue; + +cvar_t *r_norefresh; +cvar_t *r_drawentities; +cvar_t *r_drawworld; +cvar_t *r_drawfog; +cvar_t *r_speeds; +cvar_t *r_fullbright; +cvar_t *r_novis; +cvar_t *r_nocull; +cvar_t *r_facePlaneCull; +cvar_t *r_showcluster; +cvar_t *r_nocurves; + +cvar_t *r_allowExtensions; + +cvar_t *r_ext_compressed_textures; +cvar_t *r_ext_multitexture; +cvar_t *r_ext_compiled_vertex_array; +cvar_t *r_ext_texture_env_add; +cvar_t *r_ext_texture_filter_anisotropic; +cvar_t *r_ext_preferred_tc_method; + +cvar_t *r_ext_draw_range_elements; +cvar_t *r_ext_multi_draw_arrays; +cvar_t *r_ext_texture_float; +cvar_t *r_arb_half_float_pixel; +cvar_t *r_ext_framebuffer_multisample; +cvar_t *r_arb_seamless_cube_map; +cvar_t *r_arb_vertex_type_2_10_10_10_rev; +cvar_t *r_arb_buffer_storage; + +cvar_t *r_mergeMultidraws; +cvar_t *r_mergeLeafSurfaces; + +cvar_t *r_cameraExposure; + +cvar_t *r_externalGLSL; + +cvar_t *r_hdr; +cvar_t *r_floatLightmap; + +cvar_t *r_toneMap; +cvar_t *r_forceToneMap; +cvar_t *r_forceToneMapMin; +cvar_t *r_forceToneMapAvg; +cvar_t *r_forceToneMapMax; + +cvar_t *r_autoExposure; +cvar_t *r_forceAutoExposure; +cvar_t *r_forceAutoExposureMin; +cvar_t *r_forceAutoExposureMax; + +cvar_t *r_depthPrepass; +cvar_t *r_ssao; + +cvar_t *r_normalMapping; +cvar_t *r_specularMapping; +cvar_t *r_deluxeMapping; +cvar_t *r_deluxeSpecular; +cvar_t *r_parallaxMapping; +cvar_t *r_forceParallaxBias; +cvar_t *r_cubeMapping; +cvar_t *r_cubeMappingBounces; +cvar_t *r_baseNormalX; +cvar_t *r_baseNormalY; +cvar_t *r_baseParallax; +cvar_t *r_baseSpecular; +cvar_t *r_dlightMode; +cvar_t *r_pshadowDist; +cvar_t *r_imageUpsample; +cvar_t *r_imageUpsampleMaxSize; +cvar_t *r_imageUpsampleType; +cvar_t *r_genNormalMaps; +cvar_t *r_forceSun; +cvar_t *r_forceSunMapLightScale; +cvar_t *r_forceSunLightScale; +cvar_t *r_forceSunAmbientScale; +cvar_t *r_sunlightMode; +cvar_t *r_drawSunRays; +cvar_t *r_sunShadows; +cvar_t *r_shadowFilter; +cvar_t *r_shadowMapSize; +cvar_t *r_shadowCascadeZNear; +cvar_t *r_shadowCascadeZFar; +cvar_t *r_shadowCascadeZBias; +cvar_t *r_ignoreDstAlpha; + +cvar_t *r_ignoreGLErrors; +cvar_t *r_logFile; + +cvar_t *r_texturebits; + +cvar_t *r_drawBuffer; +cvar_t *r_lightmap; +cvar_t *r_vertexLight; +cvar_t *r_uiFullScreen; +cvar_t *r_shadows; +cvar_t *r_flares; +cvar_t *r_nobind; +cvar_t *r_singleShader; +cvar_t *r_roundImagesDown; +cvar_t *r_colorMipLevels; +cvar_t *r_picmip; +cvar_t *r_showtris; +cvar_t *r_showsky; +cvar_t *r_shownormals; +cvar_t *r_finish; +cvar_t *r_clear; +cvar_t *r_markcount; +cvar_t *r_textureMode; +cvar_t *r_offsetFactor; +cvar_t *r_offsetUnits; +cvar_t *r_shadowOffsetFactor; +cvar_t *r_shadowOffsetUnits; +cvar_t *r_gamma; +cvar_t *r_intensity; +cvar_t *r_lockpvs; +cvar_t *r_noportals; +cvar_t *r_portalOnly; + +cvar_t *r_subdivisions; +cvar_t *r_lodCurveError; + + + +cvar_t *r_overBrightBits; +cvar_t *r_mapOverBrightBits; + +cvar_t *r_debugSurface; +cvar_t *r_simpleMipMaps; + +cvar_t *r_showImages; + +cvar_t *r_ambientScale; +cvar_t *r_directedScale; +cvar_t *r_debugLight; +cvar_t *r_debugSort; +cvar_t *r_printShaders; +cvar_t *r_saveFontData; + +#ifdef _DEBUG +cvar_t *r_noPrecacheGLA; +#endif + +cvar_t *r_noServerGhoul2; // In SP renderer CVAR is actually r_noghoul2! +cvar_t *r_Ghoul2AnimSmooth=0; +cvar_t *r_Ghoul2UnSqashAfterSmooth=0; +//cvar_t *r_Ghoul2UnSqash; +//cvar_t *r_Ghoul2TimeBase=0; from single player +//cvar_t *r_Ghoul2NoLerp; +//cvar_t *r_Ghoul2NoBlend; +//cvar_t *r_Ghoul2BlendMultiplier=0; + +cvar_t *broadsword=0; +cvar_t *broadsword_kickbones=0; +cvar_t *broadsword_kickorigin=0; +cvar_t *broadsword_playflop=0; +cvar_t *broadsword_dontstopanim=0; +cvar_t *broadsword_waitforshot=0; +cvar_t *broadsword_smallbbox=0; +cvar_t *broadsword_extra1=0; +cvar_t *broadsword_extra2=0; + +cvar_t *broadsword_effcorr=0; +cvar_t *broadsword_ragtobase=0; +cvar_t *broadsword_dircap=0; + +cvar_t *r_marksOnTriangleMeshes; + +cvar_t *r_aviMotionJpegQuality; +cvar_t *r_screenshotJpegQuality; +cvar_t *r_surfaceSprites; + +cvar_t *r_patchStitching; + +// the limits apply to the sum of all scenes in a frame -- +// the main view, all the 3D icons, etc +#define DEFAULT_MAX_POLYS 600 +#define DEFAULT_MAX_POLYVERTS 3000 +cvar_t *r_maxpolys; +cvar_t *r_maxpolyverts; +int max_polys; +int max_polyverts; + +cvar_t *r_dynamicGlow; +cvar_t *r_dynamicGlowPasses; +cvar_t *r_dynamicGlowDelta; +cvar_t *r_dynamicGlowIntensity; +cvar_t *r_dynamicGlowSoft; +cvar_t *r_dynamicGlowWidth; +cvar_t *r_dynamicGlowHeight; + +cvar_t *r_debugContext; +cvar_t *r_debugWeather; + +cvar_t *r_aspectCorrectFonts; + +cvar_t* com_buildScript; +cvar_t* sv_mapname; +cvar_t* sv_mapChecksum; +cvar_t* r_modelpoolmegs; +cvar_t* r_environmentMapping; +cvar_t* r_ext_compressed_lightmaps; + +#define ri_Cvar_Get_NoComm(varname, value, flag, comment) ri.Cvar_Get(varname, value, flag) + +#ifdef REND2_SP +static qboolean gbAllowScreenDissolve = qtrue; +extern qboolean RE_InitDissolve(qboolean bForceCircularExtroWipe); +extern qboolean RE_ProcessDissolve(void); +#endif // REND2_SP + +// STUBS, REPLACEME + +void stub_R_InitWorldEffects(void) {} +bool stub_R_SetTempGlobalFogColor(vec3_t color) { return qfalse; } + +float tr_distortionAlpha = 1.0f; //opaque +float tr_distortionStretch = 0.0f; //no stretch override +qboolean tr_distortionPrePost = qfalse; //capture before postrender phase? +qboolean tr_distortionNegate = qfalse; //negative blend mode +float* stub_get_tr_distortionAlpha(void) { return &tr_distortionAlpha; } +float* stub_get_tr_distortionStretch(void) { return &tr_distortionStretch; } +qboolean* stub_get_tr_distortionPrePost(void) { return &tr_distortionPrePost; } +qboolean* stub_get_tr_distortionNegate(void) { return &tr_distortionNegate; } + +extern void RB_SetGL2D (void); +static void R_Splash() +{ + const GLfloat black[] = { 0.0f, 0.0f, 0.0f, 1.0f }; + + GL_SetViewportAndScissor( 0, 0, glConfig.vidWidth, glConfig.vidHeight ); + qglClearBufferfv(GL_COLOR, 0, black); + qglClear(GL_DEPTH_BUFFER_BIT); + + GLSL_InitSplashScreenShader(); + + GL_Cull(CT_TWO_SIDED); + + image_t *pImage = R_FindImageFile( "menu/splash", IMGTYPE_COLORALPHA, IMGFLAG_NONE); + if (pImage ) + GL_Bind( pImage ); + + GL_State(GLS_DEPTHTEST_DISABLE); + GLSL_BindProgram(&tr.splashScreenShader); + RB_InstantTriangle(); + + ri.WIN_Present(&window); +} + +/* +** GLW_CheckForExtension + + Cannot use strstr directly to differentiate between (for eg) reg_combiners and reg_combiners2 +*/ +bool GL_CheckForExtension(const char *ext) +{ + const char *ptr = Q_stristr( glConfigExt.originalExtensionString, ext ); + if (ptr == NULL) + return false; + ptr += strlen(ext); + return ((*ptr == ' ') || (*ptr == '\0')); // verify it's complete string. +} + + +void GLW_InitTextureCompression( void ) +{ + bool newer_tc, old_tc; + + // Check for available tc methods. + newer_tc = GL_CheckForExtension("ARB_texture_compression") && GL_CheckForExtension("EXT_texture_compression_s3tc"); + old_tc = GL_CheckForExtension("GL_S3_s3tc"); + + if ( old_tc ) + { + Com_Printf ("...GL_S3_s3tc available\n" ); + } + + if ( newer_tc ) + { + Com_Printf ("...GL_EXT_texture_compression_s3tc available\n" ); + } + + if ( !r_ext_compressed_textures->value ) + { + // Compressed textures are off + glConfig.textureCompression = TC_NONE; + Com_Printf ("...ignoring texture compression\n" ); + } + else if ( !old_tc && !newer_tc ) + { + // Requesting texture compression, but no method found + glConfig.textureCompression = TC_NONE; + Com_Printf ("...no supported texture compression method found\n" ); + Com_Printf (".....ignoring texture compression\n" ); + } + else + { + // some form of supported texture compression is avaiable, so see if the user has a preference + if ( r_ext_preferred_tc_method->integer == TC_NONE ) + { + // No preference, so pick the best + if ( newer_tc ) + { + Com_Printf ("...no tc preference specified\n" ); + Com_Printf (".....using GL_EXT_texture_compression_s3tc\n" ); + glConfig.textureCompression = TC_S3TC_DXT; + } + else + { + Com_Printf ("...no tc preference specified\n" ); + Com_Printf (".....using GL_S3_s3tc\n" ); + glConfig.textureCompression = TC_S3TC; + } + } + else + { + // User has specified a preference, now see if this request can be honored + if ( old_tc && newer_tc ) + { + // both are avaiable, so we can use the desired tc method + if ( r_ext_preferred_tc_method->integer == TC_S3TC ) + { + Com_Printf ("...using preferred tc method, GL_S3_s3tc\n" ); + glConfig.textureCompression = TC_S3TC; + } + else + { + Com_Printf ("...using preferred tc method, GL_EXT_texture_compression_s3tc\n" ); + glConfig.textureCompression = TC_S3TC_DXT; + } + } + else + { + // Both methods are not available, so this gets trickier + if ( r_ext_preferred_tc_method->integer == TC_S3TC ) + { + // Preferring to user older compression + if ( old_tc ) + { + Com_Printf ("...using GL_S3_s3tc\n" ); + glConfig.textureCompression = TC_S3TC; + } + else + { + // Drat, preference can't be honored + Com_Printf ("...preferred tc method, GL_S3_s3tc not available\n" ); + Com_Printf (".....falling back to GL_EXT_texture_compression_s3tc\n" ); + glConfig.textureCompression = TC_S3TC_DXT; + } + } + else + { + // Preferring to user newer compression + if ( newer_tc ) + { + Com_Printf ("...using GL_EXT_texture_compression_s3tc\n" ); + glConfig.textureCompression = TC_S3TC_DXT; + } + else + { + // Drat, preference can't be honored + Com_Printf ("...preferred tc method, GL_EXT_texture_compression_s3tc not available\n" ); + Com_Printf (".....falling back to GL_S3_s3tc\n" ); + glConfig.textureCompression = TC_S3TC; + } + } + } + } + } +} + +// Truncates the GL extensions string by only allowing up to 'maxExtensions' extensions in the string. +static const char *TruncateGLExtensionsString (const char *extensionsString, int maxExtensions) +{ + const char *p = extensionsString; + const char *q; + int numExtensions = 0; + size_t extensionsLen = strlen (extensionsString); + + char *truncatedExtensions; + + while ( (q = strchr (p, ' ')) != NULL && numExtensions < maxExtensions ) + { + p = q + 1; + numExtensions++; + } + + if ( q != NULL ) + { + // We still have more extensions. We'll call this the end + + extensionsLen = p - extensionsString - 1; + } + + truncatedExtensions = (char *)R_Malloc(extensionsLen + 1, TAG_GENERAL); + Q_strncpyz (truncatedExtensions, extensionsString, extensionsLen + 1); + + return truncatedExtensions; +} + +static const char *GetGLExtensionsString() +{ + GLint numExtensions; + glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions); + size_t extensionStringLen = 0; + + for ( int i = 0; i < numExtensions; i++ ) + { + extensionStringLen += strlen((const char *)qglGetStringi(GL_EXTENSIONS, i)) + 1; + } + + char *extensionString = (char *)R_Malloc(extensionStringLen + 1, TAG_GENERAL); + char *p = extensionString; + for ( int i = 0; i < numExtensions; i++ ) + { + const char *extension = (const char *)qglGetStringi(GL_EXTENSIONS, i); + while ( *extension != '\0' ) + *p++ = *extension++; + + *p++ = ' '; + } + + *p = '\0'; + assert((p - extensionString) == extensionStringLen); + + return extensionString; +} + +/* +** InitOpenGL +** +** This function is responsible for initializing a valid OpenGL subsystem. This +** is done by calling GLimp_Init (which gives us a working OGL subsystem) then +** setting variables, checking GL constants, and reporting the gfx system config +** to the user. +*/ +static void InitOpenGL( void ) +{ + // + // initialize OS specific portions of the renderer + // + // GLimp_Init directly or indirectly references the following cvars: + // - r_fullscreen + // - r_mode + // - r_(color|depth|stencil)bits + // - r_ignorehwgamma + // - r_gamma + // + + if ( glConfig.vidWidth == 0 ) + { + windowDesc_t windowDesc = {}; + memset(&glConfig, 0, sizeof(glConfig)); + + windowDesc.api = GRAPHICS_API_OPENGL; + windowDesc.gl.majorVersion = 3; + windowDesc.gl.minorVersion = 2; + windowDesc.gl.profile = GLPROFILE_CORE; + if ( r_debugContext->integer ) + windowDesc.gl.contextFlags = GLCONTEXT_DEBUG; + + window = ri.WIN_Init(&windowDesc, &glConfig); + + GLimp_InitCoreFunctions(); + + Com_Printf( "GL_RENDERER: %s\n", (char *)qglGetString (GL_RENDERER) ); + + // get our config strings + glConfig.vendor_string = (const char *)qglGetString (GL_VENDOR); + glConfig.renderer_string = (const char *)qglGetString (GL_RENDERER); + glConfig.version_string = (const char *)qglGetString (GL_VERSION); + glConfig.extensions_string = GetGLExtensionsString(); + + glConfigExt.originalExtensionString = glConfig.extensions_string; + glConfig.extensions_string = TruncateGLExtensionsString(glConfigExt.originalExtensionString, 128); + + // OpenGL driver constants + qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &glConfig.maxTextureSize ); + + // Determine GPU IHV + if ( Q_stristr( glConfig.vendor_string, "ATI Technologies Inc." ) ) + { + glRefConfig.hardwareVendor = IHV_AMD; + } + else if ( Q_stristr( glConfig.vendor_string, "NVIDIA" ) ) + { + glRefConfig.hardwareVendor = IHV_NVIDIA; + } + else if ( Q_stristr( glConfig.vendor_string, "INTEL") ) + { + glRefConfig.hardwareVendor = IHV_INTEL; + } + else + { + glRefConfig.hardwareVendor = IHV_UNKNOWN; + } + + // stubbed or broken drivers may have reported 0... + glConfig.maxTextureSize = Q_max(0, glConfig.maxTextureSize); + + // initialize extensions + GLimp_InitExtensions(); + + // Create the default VAO + GLuint vao; + qglGenVertexArrays(1, &vao); + qglBindVertexArray(vao); + tr.globalVao = vao; + + // set default state + GL_SetDefaultState(); + + R_Splash(); //get something on screen asap + } + else + { + // set default state + GL_SetDefaultState(); + } +} + +/* +================== +GL_CheckErrors +================== +*/ +void GL_CheckErrs( const char *file, int line ) { +#if defined(_DEBUG) + GLenum err; + char s[64]; + + err = qglGetError(); + if ( err == GL_NO_ERROR ) { + return; + } + if ( r_ignoreGLErrors->integer ) { + return; + } + switch( err ) { + case GL_INVALID_ENUM: + strcpy( s, "GL_INVALID_ENUM" ); + break; + case GL_INVALID_VALUE: + strcpy( s, "GL_INVALID_VALUE" ); + break; + case GL_INVALID_OPERATION: + strcpy( s, "GL_INVALID_OPERATION" ); + break; + case GL_OUT_OF_MEMORY: + strcpy( s, "GL_OUT_OF_MEMORY" ); + break; + default: + Com_sprintf( s, sizeof(s), "%i", err); + break; + } + + ri.Error( ERR_FATAL, "GL_CheckErrors: %s in %s at line %d", s , file, line); +#endif +} + +/* +============================================================================== + + SCREEN SHOTS + +NOTE TTimo +some thoughts about the screenshots system: +screenshots get written in fs_homepath + fs_gamedir +vanilla q3 .. baseq3/screenshots/ *.tga +team arena .. missionpack/screenshots/ *.tga + +two commands: "screenshot" and "screenshotJPEG" +we use statics to store a count and start writing the first screenshot/screenshot????.tga (.jpg) available +(with FS_FileExists / FS_FOpenFileWrite calls) +FIXME: the statics don't get a reinit between fs_game changes + +============================================================================== +*/ + +/* +================== +RB_ReadPixels + +Reads an image but takes care of alignment issues for reading RGB images. + +Reads a minimum offset for where the RGB data starts in the image from +integer stored at pointer offset. When the function has returned the actual +offset was written back to address offset. This address will always have an +alignment of packAlign to ensure efficient copying. + +Stores the length of padding after a line of pixels to address padlen + +Return value must be freed with R2_Hunk_FreeTempMemory() +================== +*/ + +byte *RB_ReadPixels( + int x, int y, int width, int height, size_t *offset, int *padlen) +{ + byte *buffer, *bufstart; + int padwidth, linelen; + GLint packAlign; + + qglGetIntegerv(GL_PACK_ALIGNMENT, &packAlign); + + linelen = width * 3; + padwidth = PAD(linelen, packAlign); + + // Allocate a few more bytes so that we can choose an alignment we like + buffer = (byte *)Hunk_AllocateTempMemory(padwidth * height + *offset + packAlign - 1); + + bufstart = (byte*)(PADP((intptr_t) buffer + *offset, packAlign)); + qglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, bufstart); + + *offset = bufstart - buffer; + *padlen = padwidth - linelen; + + return buffer; +} + +static void ConvertRGBtoBGR( + byte *dst, const byte *src, int stride, int width, int height) +{ + const byte *row = src; + for (int y = 0; y < height; ++y) + { + const byte *pixelRGB = row; + for (int x = 0; x < width; ++x) + { + // swap rgb to bgr + const byte temp = pixelRGB[0]; + *dst++ = pixelRGB[2]; + *dst++ = pixelRGB[1]; + *dst++ = temp; + + pixelRGB += 3; + } + + row += stride; + } +} + +static void R_SaveTGA( + const char *filename, + const byte *pixels, + int width, + int height, + int stride) +{ + const size_t headerSize = 18; + const size_t pixelBufferSize = stride * height; + const size_t bufferSize = headerSize + pixelBufferSize; + + byte *buffer = (byte *)Hunk_AllocateTempMemory(bufferSize); + + // Write TGA header + Com_Memset(buffer, 0, headerSize); + buffer[2] = 2; // uncompressed type + buffer[12] = width & 255; + buffer[13] = width >> 8; + buffer[14] = height & 255; + buffer[15] = height >> 8; + buffer[16] = 24; // pixel size + + ConvertRGBtoBGR(buffer + headerSize, pixels, stride, width, height); + + ri.FS_WriteFile(filename, buffer, bufferSize); + Hunk_FreeTempMemory(buffer); +} + +/* +================== +R_SaveScreenshotTGA +================== +*/ +static void R_SaveScreenshotTGA( + const screenshotReadback_t *screenshotReadback, byte *pixels) +{ + R_SaveTGA( + screenshotReadback->filename, + pixels, + screenshotReadback->width, + screenshotReadback->height, + screenshotReadback->strideInBytes); +} + +/* +================== +R_SaveScreenshotPNG +================== +*/ +static void R_SaveScreenshotPNG( + const screenshotReadback_t *screenshotReadback, byte *pixels) +{ + RE_SavePNG( + screenshotReadback->filename, + pixels, + screenshotReadback->width, + screenshotReadback->height, + 3); +} + +/* +================== +R_SaveScreenshotJPG +================== +*/ +static void R_SaveScreenshotJPG( + const screenshotReadback_t *screenshotReadback, byte *pixels) +{ + RE_SaveJPG( + screenshotReadback->filename, + r_screenshotJpegQuality->integer, + screenshotReadback->width, + screenshotReadback->height, + pixels, + screenshotReadback->strideInBytes - screenshotReadback->rowInBytes); +} + +void R_SaveScreenshot(screenshotReadback_t *screenshotReadback) +{ + qglBindBuffer(GL_PIXEL_PACK_BUFFER, screenshotReadback->pbo); + + byte *pixelBuffer = static_cast( + qglMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY)); + + if (pixelBuffer == nullptr) + { + ri.Printf( + PRINT_ALL, + S_COLOR_RED "Failed to read screenshot data from GPU\n"); + } + else + { + const int height = screenshotReadback->height; + const int stride = screenshotReadback->strideInBytes; + const size_t pixelBufferSize = stride * height; + + byte *pixels = (byte *)Hunk_AllocateTempMemory(pixelBufferSize); + Com_Memcpy(pixels, pixelBuffer, pixelBufferSize); + qglUnmapBuffer(GL_PIXEL_PACK_BUFFER); + + if (glConfig.deviceSupportsGamma) + R_GammaCorrect(pixels, pixelBufferSize); + + switch (screenshotReadback->format) + { + case SSF_JPEG: + R_SaveScreenshotJPG(screenshotReadback, pixels); + break; + + case SSF_TGA: + R_SaveScreenshotTGA(screenshotReadback, pixels); + break; + + case SSF_PNG: + R_SaveScreenshotPNG(screenshotReadback, pixels); + break; + } + + Hunk_FreeTempMemory(pixels); + } + + qglDeleteBuffers(1, &screenshotReadback->pbo); + screenshotReadback->pbo = 0; +} + +/* +================== +R_TakeScreenshotCmd +================== +*/ +const void *RB_TakeScreenshotCmd( const void *data ) { + const screenshotCommand_t *cmd; + + cmd = (const screenshotCommand_t *)data; + + // finish any 2D drawing if needed + if (tess.numIndexes) + RB_EndSurface(); + + const int frameNumber = backEndData->realFrameNumber; + gpuFrame_t *thisFrame = &backEndData->frames[frameNumber % MAX_FRAMES]; + screenshotReadback_t *screenshot = &thisFrame->screenshotReadback; + + GLint packAlign; + qglGetIntegerv(GL_PACK_ALIGNMENT, &packAlign); + + const int linelen = cmd->width * 3; + const int strideInBytes = PAD(linelen, packAlign); + + qglGenBuffers(1, &screenshot->pbo); + qglBindBuffer(GL_PIXEL_PACK_BUFFER, screenshot->pbo); + qglBufferData( + GL_PIXEL_PACK_BUFFER, + strideInBytes * cmd->height, + nullptr, + GL_STATIC_COPY); + qglReadPixels( + cmd->x, cmd->y, cmd->width, cmd->height, GL_RGB, GL_UNSIGNED_BYTE, 0); + + screenshot->strideInBytes = strideInBytes; + screenshot->rowInBytes = linelen; + screenshot->width = cmd->width; + screenshot->height = cmd->height; + screenshot->format = cmd->format; + Q_strncpyz( + screenshot->filename, cmd->fileName, sizeof(screenshot->filename)); + + return (const void *)(cmd + 1); +} + +/* +================== +R_TakeScreenshot +================== +*/ +void R_TakeScreenshot( int x, int y, int width, int height, char *name, screenshotFormat_t format ) { + static char fileName[MAX_OSPATH]; // bad things if two screenshots per frame? + screenshotCommand_t *cmd; + + cmd = (screenshotCommand_t *)R_GetCommandBuffer( sizeof( *cmd ) ); + if ( !cmd ) { + return; + } + cmd->commandId = RC_SCREENSHOT; + + cmd->x = x; + cmd->y = y; + cmd->width = width; + cmd->height = height; + Q_strncpyz( fileName, name, sizeof(fileName) ); + cmd->fileName = fileName; + cmd->format = format; +} + +/* +================== +R_ScreenshotFilename +================== +*/ +void R_ScreenshotFilename( char *buf, int bufSize, const char *ext ) { + time_t rawtime; + char timeStr[32] = {0}; // should really only reach ~19 chars + + time( &rawtime ); + strftime( timeStr, sizeof( timeStr ), "%Y-%m-%d_%H-%M-%S", localtime( &rawtime ) ); // or gmtime + + Com_sprintf( buf, bufSize, "screenshots/shot%s%s", timeStr, ext ); +} + +/* +==================== +R_LevelShot + +levelshots are specialized 256*256 thumbnails for +the menu system, sampled down from full screen distorted images +==================== +*/ +#define LEVELSHOTSIZE 256 +static void R_LevelShot( void ) { + char checkname[MAX_OSPATH]; + byte *buffer; + byte *source, *allsource; + byte *src, *dst; + size_t offset = 0; + int padlen; + int x, y; + int r, g, b; + float xScale, yScale; + int xx, yy; + + Com_sprintf( checkname, sizeof(checkname), "levelshots/%s.tga", tr.world->baseName ); + + allsource = RB_ReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, &offset, &padlen); + source = allsource + offset; + + buffer = (byte *)Hunk_AllocateTempMemory(LEVELSHOTSIZE * LEVELSHOTSIZE*3 + 18); + Com_Memset (buffer, 0, 18); + buffer[2] = 2; // uncompressed type + buffer[12] = LEVELSHOTSIZE & 255; + buffer[13] = LEVELSHOTSIZE >> 8; + buffer[14] = LEVELSHOTSIZE & 255; + buffer[15] = LEVELSHOTSIZE >> 8; + buffer[16] = 24; // pixel size + + // resample from source + xScale = glConfig.vidWidth / (4.0*LEVELSHOTSIZE); + yScale = glConfig.vidHeight / (3.0*LEVELSHOTSIZE); + for ( y = 0 ; y < LEVELSHOTSIZE ; y++ ) { + for ( x = 0 ; x < LEVELSHOTSIZE ; x++ ) { + r = g = b = 0; + for ( yy = 0 ; yy < 3 ; yy++ ) { + for ( xx = 0 ; xx < 4 ; xx++ ) { + src = source + 3 * ( glConfig.vidWidth * (int)( (y*3+yy)*yScale ) + (int)( (x*4+xx)*xScale ) ); + r += src[0]; + g += src[1]; + b += src[2]; + } + } + dst = buffer + 18 + 3 * ( y * LEVELSHOTSIZE + x ); + dst[0] = b / 12; + dst[1] = g / 12; + dst[2] = r / 12; + } + } + + // gamma correct + if ( ( tr.overbrightBits > 0 ) && glConfig.deviceSupportsGamma ) { + R_GammaCorrect( buffer + 18, LEVELSHOTSIZE * LEVELSHOTSIZE * 3 ); + } + + ri.FS_WriteFile( checkname, buffer, LEVELSHOTSIZE * LEVELSHOTSIZE*3 + 18 ); + + Hunk_FreeTempMemory( buffer ); + Hunk_FreeTempMemory( allsource ); + + ri.Printf( PRINT_ALL, "Wrote %s\n", checkname ); +} + +/* +================== +R_ScreenShotTGA_f + +screenshot +screenshot [silent] +screenshot [levelshot] +screenshot [filename] + +Doesn't print the pacifier message if there is a second arg +================== +*/ +void R_ScreenShotTGA_f (void) { + char checkname[MAX_OSPATH] = {0}; + qboolean silent = qfalse; + + if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) { + R_LevelShot(); + return; + } + + if ( !strcmp( ri.Cmd_Argv(1), "silent" ) ) + silent = qtrue; + + if ( ri.Cmd_Argc() == 2 && !silent ) { + // explicit filename + Com_sprintf( checkname, sizeof( checkname ), "screenshots/%s.tga", ri.Cmd_Argv( 1 ) ); + } + else { + // timestamp the file + R_ScreenshotFilename( checkname, sizeof( checkname ), ".tga" ); + + if ( ri.FS_FileExists( checkname ) ) { + Com_Printf( "ScreenShot: Couldn't create a file\n"); + return; + } + } + + R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, SSF_TGA ); + + if ( !silent ) + ri.Printf (PRINT_ALL, "Wrote %s\n", checkname); +} + +void R_ScreenShotPNG_f (void) { + char checkname[MAX_OSPATH] = {0}; + qboolean silent = qfalse; + + if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) { + R_LevelShot(); + return; + } + + if ( !strcmp( ri.Cmd_Argv(1), "silent" ) ) + silent = qtrue; + + if ( ri.Cmd_Argc() == 2 && !silent ) { + // explicit filename + Com_sprintf( checkname, sizeof( checkname ), "screenshots/%s.png", ri.Cmd_Argv( 1 ) ); + } + else { + // timestamp the file + R_ScreenshotFilename( checkname, sizeof( checkname ), ".png" ); + + if ( ri.FS_FileExists( checkname ) ) { + Com_Printf( "ScreenShot: Couldn't create a file\n"); + return; + } + } + + R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, SSF_PNG ); + + if ( !silent ) + ri.Printf (PRINT_ALL, "Wrote %s\n", checkname); +} + +void R_ScreenShotJPEG_f (void) { + char checkname[MAX_OSPATH] = {0}; + qboolean silent = qfalse; + + if ( !strcmp( ri.Cmd_Argv(1), "levelshot" ) ) { + R_LevelShot(); + return; + } + + if ( !strcmp( ri.Cmd_Argv(1), "silent" ) ) + silent = qtrue; + + if ( ri.Cmd_Argc() == 2 && !silent ) { + // explicit filename + Com_sprintf( checkname, sizeof( checkname ), "screenshots/%s.jpg", ri.Cmd_Argv( 1 ) ); + } + else { + // timestamp the file + R_ScreenshotFilename( checkname, sizeof( checkname ), ".jpg" ); + + if ( ri.FS_FileExists( checkname ) ) { + Com_Printf( "ScreenShot: Couldn't create a file\n"); + return; + } + } + + R_TakeScreenshot( 0, 0, glConfig.vidWidth, glConfig.vidHeight, checkname, SSF_JPEG ); + + if ( !silent ) + ri.Printf (PRINT_ALL, "Wrote %s\n", checkname); +} + +//============================================================================ + +/* +================== +RB_TakeVideoFrameCmd +================== +*/ + +const void *RB_TakeVideoFrameCmd( const void *data ) +{ + const videoFrameCommand_t *cmd; + + // finish any 2D drawing if needed + if (tess.numIndexes) + RB_EndSurface(); + + cmd = (const videoFrameCommand_t *)data; +#ifndef REND2_SP + byte *cBuf; + size_t memcount, linelen; + int padwidth, avipadwidth, padlen, avipadlen; + GLint packAlign; + + qglGetIntegerv(GL_PACK_ALIGNMENT, &packAlign); + + linelen = cmd->width * 3; + + // Alignment stuff for glReadPixels + padwidth = PAD(linelen, packAlign); + padlen = padwidth - linelen; + // AVI line padding + avipadwidth = PAD(linelen, AVI_LINE_PADDING); + avipadlen = avipadwidth - linelen; + + cBuf = (byte*)(PADP(cmd->captureBuffer, packAlign)); + + qglReadPixels(0, 0, cmd->width, cmd->height, GL_RGB, + GL_UNSIGNED_BYTE, cBuf); + + memcount = padwidth * cmd->height; + + // gamma correct + if(glConfig.deviceSupportsGamma) + R_GammaCorrect(cBuf, memcount); + + if(cmd->motionJpeg) + { + memcount = RE_SaveJPGToBuffer(cmd->encodeBuffer, linelen * cmd->height, + r_aviMotionJpegQuality->integer, + cmd->width, cmd->height, cBuf, padlen); + ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, memcount); + } + else + { + byte *lineend, *memend; + byte *srcptr, *destptr; + + srcptr = cBuf; + destptr = cmd->encodeBuffer; + memend = srcptr + memcount; + + // swap R and B and remove line paddings + while(srcptr < memend) + { + lineend = srcptr + linelen; + while(srcptr < lineend) + { + *destptr++ = srcptr[2]; + *destptr++ = srcptr[1]; + *destptr++ = srcptr[0]; + srcptr += 3; + } + + Com_Memset(destptr, '\0', avipadlen); + destptr += avipadlen; + + srcptr += padlen; + } + + ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, avipadwidth * cmd->height); + } +#endif + return (const void *)(cmd + 1); +} + + +//============================================================================ + +/* +** GL_SetDefaultState +*/ +void GL_SetDefaultState( void ) +{ + qglClearDepth( 1.0f ); + + qglCullFace(GL_FRONT); + + // initialize downstream texture unit if we're running + // in a multitexture environment + GL_SelectTexture( 1 ); + GL_TextureMode( r_textureMode->string ); + GL_SelectTexture( 0 ); + + GL_TextureMode( r_textureMode->string ); + + //qglShadeModel( GL_SMOOTH ); + qglDepthFunc( GL_LEQUAL ); + + Com_Memset(&glState, 0, sizeof(glState)); + + // + // make sure our GL state vector is set correctly + // + glState.glStateBits = GLS_DEPTHTEST_DISABLE | GLS_DEPTHMASK_TRUE; + glState.maxDepth = 1.0f; + qglDepthRange(0.0f, 1.0f); + + qglUseProgram(0); + + qglBindBuffer(GL_ARRAY_BUFFER, 0); + qglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + + qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + qglDepthMask( GL_TRUE ); + qglDisable( GL_DEPTH_TEST ); + qglEnable( GL_SCISSOR_TEST ); + qglEnable(GL_PROGRAM_POINT_SIZE); + qglDisable( GL_CULL_FACE ); + qglDisable( GL_BLEND ); + glState.blend = false; + + qglEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + + qglStencilFunc(GL_ALWAYS, 0, 0xff); + qglStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP); + qglStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_KEEP); + + // set default vertex color + qglVertexAttrib4f(ATTR_INDEX_COLOR, 1.0f, 1.0f, 1.0f, 1.0f); +} + +/* +================ +R_PrintLongString + +Workaround for ri.Printf's 1024 characters buffer limit. +================ +*/ +void R_PrintLongString(const char *string) { + char buffer[1024]; + const char *p; + int size = strlen(string); + + p = string; + while(size > 0) + { + Q_strncpyz(buffer, p, sizeof (buffer) ); + ri.Printf( PRINT_ALL, "%s", buffer ); + p += 1023; + size -= 1023; + } +} + +/* +================ +GfxInfo_f +================ +*/ +static void GfxInfo_f( void ) +{ + const char *enablestrings[] = + { + "disabled", + "enabled" + }; + const char *fsstrings[] = + { + "windowed", + "fullscreen" + }; + const char *noborderstrings[] = + { + "", + "noborder " + }; + + int fullscreen = ri.Cvar_VariableIntegerValue("r_fullscreen"); + int noborder = ri.Cvar_VariableIntegerValue("r_noborder"); + + ri.Printf( PRINT_ALL, "\nGL_VENDOR: %s\n", glConfig.vendor_string ); + ri.Printf( PRINT_ALL, "GL_RENDERER: %s\n", glConfig.renderer_string ); + ri.Printf( PRINT_ALL, "GL_VERSION: %s\n", glConfig.version_string ); + ri.Printf( PRINT_ALL, "GL_EXTENSIONS: " ); + R_PrintLongString( glConfigExt.originalExtensionString ); + ri.Printf( PRINT_ALL, "\n" ); + ri.Printf( PRINT_ALL, "GL_MAX_TEXTURE_SIZE: %d\n", glConfig.maxTextureSize ); + ri.Printf( PRINT_ALL, "\nPIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits ); + ri.Printf( PRINT_ALL, "MODE: %d, %d x %d %s%s hz:", + ri.Cvar_VariableIntegerValue("r_mode"), + glConfig.vidWidth, glConfig.vidHeight, + fullscreen == 0 ? noborderstrings[noborder == 1] : noborderstrings[0], + fsstrings[fullscreen == 1] ); + if ( glConfig.displayFrequency ) + { + ri.Printf( PRINT_ALL, "%d\n", glConfig.displayFrequency ); + } + else + { + ri.Printf( PRINT_ALL, "N/A\n" ); + } + if ( glConfig.deviceSupportsGamma ) + { + ri.Printf( PRINT_ALL, "GAMMA: hardware w/ %d overbright bits\n", tr.overbrightBits ); + } + else + { + ri.Printf( PRINT_ALL, "GAMMA: software w/ %d overbright bits\n", tr.overbrightBits ); + } + + ri.Printf( PRINT_ALL, "texturemode: %s\n", r_textureMode->string ); + ri.Printf( PRINT_ALL, "picmip: %d\n", r_picmip->integer ); + ri.Printf( PRINT_ALL, "texture bits: %d\n", r_texturebits->integer ); + + if ( r_vertexLight->integer ) + { + ri.Printf( PRINT_ALL, "HACK: using vertex lightmap approximation\n" ); + } + int displayRefresh = ri.Cvar_VariableIntegerValue("r_displayRefresh"); + if ( displayRefresh ) { + ri.Printf( PRINT_ALL, "Display refresh set to %d\n", displayRefresh ); + } + + if ( r_finish->integer ) { + ri.Printf( PRINT_ALL, "Forcing glFinish\n" ); + } + + ri.Printf( PRINT_ALL, "Dynamic Glow: %s\n", enablestrings[r_dynamicGlow->integer != 0] ); +} + +/* +================ +GfxMemInfo_f +================ +*/ +void GfxMemInfo_f( void ) +{ + switch (glRefConfig.memInfo) + { + case MI_NONE: + { + ri.Printf(PRINT_ALL, "No extension found for GPU memory info.\n"); + } + break; + case MI_NVX: + { + int value; + + qglGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &value); + ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX: %ikb\n", value); + + qglGetIntegerv(GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &value); + ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX: %ikb\n", value); + + qglGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &value); + ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX: %ikb\n", value); + + qglGetIntegerv(GL_GPU_MEMORY_INFO_EVICTION_COUNT_NVX, &value); + ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_EVICTION_COUNT_NVX: %i\n", value); + + qglGetIntegerv(GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX, &value); + ri.Printf(PRINT_ALL, "GPU_MEMORY_INFO_EVICTED_MEMORY_NVX: %ikb\n", value); + } + break; + case MI_ATI: + { + // GL_ATI_meminfo + int value[4]; + + qglGetIntegerv(GL_VBO_FREE_MEMORY_ATI, &value[0]); + ri.Printf(PRINT_ALL, "VBO_FREE_MEMORY_ATI: %ikb total %ikb largest aux: %ikb total %ikb largest\n", value[0], value[1], value[2], value[3]); + + qglGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, &value[0]); + ri.Printf(PRINT_ALL, "TEXTURE_FREE_MEMORY_ATI: %ikb total %ikb largest aux: %ikb total %ikb largest\n", value[0], value[1], value[2], value[3]); + + qglGetIntegerv(GL_RENDERBUFFER_FREE_MEMORY_ATI, &value[0]); + ri.Printf(PRINT_ALL, "RENDERBUFFER_FREE_MEMORY_ATI: %ikb total %ikb largest aux: %ikb total %ikb largest\n", value[0], value[1], value[2], value[3]); + } + break; + } +} + +static void R_CaptureFrameData_f() +{ + int argc = ri.Cmd_Argc(); + if ( argc <= 1 ) + { + ri.Printf( PRINT_ALL, "Usage: %s \n", ri.Cmd_Argv(0)); + return; + } + + + const char *cmd = ri.Cmd_Argv(1); + if ( Q_stricmp(cmd, "single") == 0 ) + tr.numFramesToCapture = 1; + else if ( Q_stricmp(cmd, "multi") == 0 ) + tr.numFramesToCapture = atoi(ri.Cmd_Argv(1)); + + int len = ri.FS_FOpenFileByMode("rend2.log", &tr.debugFile, FS_APPEND); + if ( len == -1 || !tr.debugFile ) + { + ri.Printf( PRINT_ERROR, "Failed to open rend2 log file\n" ); + tr.numFramesToCapture = 0; + } +} + +typedef struct consoleCommand_s { + const char *cmd; + xcommand_t func; +} consoleCommand_t; + +static consoleCommand_t commands[] = { + { "imagelist", R_ImageList_f }, + { "shaderlist", R_ShaderList_f }, + { "skinlist", R_SkinList_f }, + { "fontlist", R_FontList_f }, + { "screenshot", R_ScreenShotJPEG_f }, + { "screenshot_png", R_ScreenShotPNG_f }, + { "screenshot_tga", R_ScreenShotTGA_f }, + { "gfxinfo", GfxInfo_f }, + { "gfxmeminfo", GfxMemInfo_f }, + { "r_we", R_WorldEffect_f }, + //{ "imagecacheinfo", RE_RegisterImages_Info_f }, + { "modellist", R_Modellist_f }, + //{ "modelcacheinfo", RE_RegisterModels_Info_f }, + { "vbolist", R_VBOList_f }, + { "capframes", R_CaptureFrameData_f }, +}; + +static const size_t numCommands = ARRAY_LEN( commands ); + + +/* +=============== +R_Register +=============== +*/ +void R_Register( void ) +{ + // + // latched and archived variables + // + r_allowExtensions = ri_Cvar_Get_NoComm( "r_allowExtensions", "1", CVAR_ARCHIVE | CVAR_LATCH, "Allow GL extensions" ); + r_ext_compressed_textures = ri_Cvar_Get_NoComm( "r_ext_compress_textures", "0", CVAR_ARCHIVE | CVAR_LATCH, "Disable/enable texture compression" ); + r_ext_compressed_lightmaps = ri.Cvar_Get("r_ext_compress_lightmaps", "0", CVAR_ARCHIVE_ND | CVAR_LATCH); + r_ext_multitexture = ri_Cvar_Get_NoComm( "r_ext_multitexture", "1", CVAR_ARCHIVE | CVAR_LATCH, "Unused" ); + r_ext_compiled_vertex_array = ri_Cvar_Get_NoComm( "r_ext_compiled_vertex_array", "1", CVAR_ARCHIVE | CVAR_LATCH, "Unused" ); + r_ext_texture_env_add = ri_Cvar_Get_NoComm( "r_ext_texture_env_add", "1", CVAR_ARCHIVE | CVAR_LATCH, "Unused" ); + r_ext_preferred_tc_method = ri_Cvar_Get_NoComm( "r_ext_preferred_tc_method", "0", CVAR_ARCHIVE | CVAR_LATCH, "Preferred texture compression method" ); + + r_ext_draw_range_elements = ri_Cvar_Get_NoComm( "r_ext_draw_range_elements", "1", CVAR_ARCHIVE | CVAR_LATCH, "Unused" ); + r_ext_multi_draw_arrays = ri_Cvar_Get_NoComm( "r_ext_multi_draw_arrays", "1", CVAR_ARCHIVE | CVAR_LATCH, "Unused" ); + r_ext_texture_float = ri_Cvar_Get_NoComm( "r_ext_texture_float", "1", CVAR_ARCHIVE | CVAR_LATCH, "Disable/enable floating-point textures" ); + r_arb_half_float_pixel = ri_Cvar_Get_NoComm( "r_arb_half_float_pixel", "1", CVAR_ARCHIVE | CVAR_LATCH, "Disable/enable ARB_half_float GL extension" ); + r_ext_framebuffer_multisample = ri_Cvar_Get_NoComm( "r_ext_multisample", "0", CVAR_ARCHIVE | CVAR_LATCH, "Disable/enable framebuffer MSAA" ); + r_arb_seamless_cube_map = ri_Cvar_Get_NoComm( "r_arb_seamless_cube_map", "0", CVAR_ARCHIVE | CVAR_LATCH, "Disable/enable seamless cube map filtering GL extension" ); + r_arb_vertex_type_2_10_10_10_rev = ri_Cvar_Get_NoComm( "r_arb_vertex_type_2_10_10_10_rev", "1", CVAR_ARCHIVE | CVAR_LATCH, "Disable/enable 1010102 UI data type" ); + r_arb_buffer_storage = ri_Cvar_Get_NoComm( "r_arb_buffer_storage", "0", CVAR_ARCHIVE | CVAR_LATCH, "Disable/enable buffer storage GL extension" ); + r_ext_texture_filter_anisotropic = ri_Cvar_Get_NoComm( "r_ext_texture_filter_anisotropic", "16", CVAR_ARCHIVE, "Disable/enable anisotropic texture filtering" ); + + r_dynamicGlow = ri_Cvar_Get_NoComm( "r_dynamicGlow", "0", CVAR_ARCHIVE, "" ); + r_dynamicGlowPasses = ri_Cvar_Get_NoComm( "r_dynamicGlowPasses", "5", CVAR_ARCHIVE, "" ); + r_dynamicGlowDelta = ri_Cvar_Get_NoComm( "r_dynamicGlowDelta", "0.8f", CVAR_ARCHIVE, "" ); + r_dynamicGlowIntensity = ri_Cvar_Get_NoComm( "r_dynamicGlowIntensity", "1.13f", CVAR_ARCHIVE, "" ); + r_dynamicGlowSoft = ri_Cvar_Get_NoComm( "r_dynamicGlowSoft", "1", CVAR_ARCHIVE, "" ); + r_dynamicGlowWidth = ri_Cvar_Get_NoComm( "r_dynamicGlowWidth", "320", CVAR_ARCHIVE|CVAR_LATCH, "" ); + r_dynamicGlowHeight = ri_Cvar_Get_NoComm( "r_dynamicGlowHeight", "240", CVAR_ARCHIVE|CVAR_LATCH, "" ); + + r_debugContext = ri_Cvar_Get_NoComm( "r_debugContext", "0", CVAR_LATCH, "" ); + r_debugWeather = ri_Cvar_Get_NoComm( "r_debugWeather", "0", CVAR_ARCHIVE, "" ); + + r_picmip = ri_Cvar_Get_NoComm ("r_picmip", "0", CVAR_ARCHIVE | CVAR_LATCH, "" ); + ri.Cvar_CheckRange( r_picmip, 0, 16, qtrue ); + r_roundImagesDown = ri_Cvar_Get_NoComm ("r_roundImagesDown", "1", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_colorMipLevels = ri_Cvar_Get_NoComm ("r_colorMipLevels", "0", CVAR_LATCH, "" ); + r_detailTextures = ri_Cvar_Get_NoComm( "r_detailtextures", "1", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_texturebits = ri_Cvar_Get_NoComm( "r_texturebits", "0", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_overBrightBits = ri_Cvar_Get_NoComm ("r_overBrightBits", "0", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_simpleMipMaps = ri_Cvar_Get_NoComm( "r_simpleMipMaps", "1", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_vertexLight = ri_Cvar_Get_NoComm( "r_vertexLight", "0", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_uiFullScreen = ri_Cvar_Get_NoComm( "r_uifullscreen", "0", 0, ""); + r_subdivisions = ri_Cvar_Get_NoComm ("r_subdivisions", "4", CVAR_ARCHIVE | CVAR_LATCH, ""); + ri.Cvar_CheckRange( r_subdivisions, 4, 80, qfalse ); + r_stereo = ri_Cvar_Get_NoComm( "r_stereo", "0", CVAR_ARCHIVE | CVAR_LATCH, ""); + r_greyscale = ri_Cvar_Get_NoComm("r_greyscale", "0", CVAR_ARCHIVE | CVAR_LATCH, ""); + ri.Cvar_CheckRange(r_greyscale, 0, 1, qfalse); + + r_externalGLSL = ri_Cvar_Get_NoComm( "r_externalGLSL", "0", CVAR_LATCH, "" ); + + r_hdr = ri_Cvar_Get_NoComm( "r_hdr", "1", CVAR_ARCHIVE | CVAR_LATCH, "Disable/enable rendering in HDR" ); + r_floatLightmap = ri_Cvar_Get_NoComm( "r_floatLightmap", "0", CVAR_ARCHIVE | CVAR_LATCH, "Disable/enable HDR lightmap support" ); + + r_toneMap = ri_Cvar_Get_NoComm( "r_toneMap", "1", CVAR_ARCHIVE | CVAR_LATCH, "Disable/enable tonemapping" ); + r_forceToneMap = ri_Cvar_Get_NoComm( "r_forceToneMap", "0", CVAR_CHEAT, "" ); + r_forceToneMapMin = ri_Cvar_Get_NoComm( "r_forceToneMapMin", "-8.0", CVAR_CHEAT, "" ); + r_forceToneMapAvg = ri_Cvar_Get_NoComm( "r_forceToneMapAvg", "-2.0", CVAR_CHEAT, "" ); + r_forceToneMapMax = ri_Cvar_Get_NoComm( "r_forceToneMapMax", "0.0", CVAR_CHEAT, "" ); + + r_autoExposure = ri_Cvar_Get_NoComm( "r_autoExposure", "1", CVAR_ARCHIVE, "Disable/enable auto exposure" ); + r_forceAutoExposure = ri_Cvar_Get_NoComm( "r_forceAutoExposure", "0", CVAR_CHEAT, "" ); + r_forceAutoExposureMin = ri_Cvar_Get_NoComm( "r_forceAutoExposureMin", "-2.0", CVAR_CHEAT, "" ); + r_forceAutoExposureMax = ri_Cvar_Get_NoComm( "r_forceAutoExposureMax", "2.0", CVAR_CHEAT, "" ); + + r_cameraExposure = ri_Cvar_Get_NoComm( "r_cameraExposure", "0", CVAR_CHEAT, "" ); + + r_depthPrepass = ri_Cvar_Get_NoComm( "r_depthPrepass", "1", CVAR_ARCHIVE, "" ); + r_ssao = ri_Cvar_Get_NoComm( "r_ssao", "0", CVAR_LATCH | CVAR_ARCHIVE, "" ); + + r_normalMapping = ri_Cvar_Get_NoComm( "r_normalMapping", "1", CVAR_ARCHIVE | CVAR_LATCH, "Disable/enable normal mapping" ); + r_specularMapping = ri_Cvar_Get_NoComm( "r_specularMapping", "1", CVAR_ARCHIVE | CVAR_LATCH, "Disable/enable specular mapping" ); + r_deluxeMapping = ri_Cvar_Get_NoComm( "r_deluxeMapping", "1", CVAR_ARCHIVE | CVAR_LATCH, "Disable/enable reading deluxemaps when compiled with q3map2" ); + r_deluxeSpecular = ri_Cvar_Get_NoComm("r_deluxeSpecular", "1", CVAR_ARCHIVE | CVAR_LATCH, "Disable/enable/scale the specular response from deluxemaps"); + r_parallaxMapping = ri_Cvar_Get_NoComm( "r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH, "Disable/enable parallax mapping" ); + r_cubeMapping = ri_Cvar_Get_NoComm( "r_cubeMapping", "0", CVAR_ARCHIVE | CVAR_LATCH, "Disable/enable cubemapping" ); + r_cubeMappingBounces = ri_Cvar_Get_NoComm("r_cubeMappingBounces", "0", CVAR_ARCHIVE | CVAR_LATCH, "Renders cubemaps multiple times to get reflections in reflections"); + ri.Cvar_CheckRange(r_cubeMappingBounces, 0, 2, qfalse); + r_baseNormalX = ri_Cvar_Get_NoComm( "r_baseNormalX", "1.0", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_baseNormalY = ri_Cvar_Get_NoComm( "r_baseNormalY", "1.0", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_baseParallax = ri_Cvar_Get_NoComm( "r_baseParallax", "0.05", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_baseSpecular = ri_Cvar_Get_NoComm( "r_baseSpecular", "0.04", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_dlightMode = ri_Cvar_Get_NoComm( "r_dlightMode", "1", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_pshadowDist = ri_Cvar_Get_NoComm( "r_pshadowDist", "128", CVAR_ARCHIVE, "" ); + r_imageUpsample = ri_Cvar_Get_NoComm( "r_imageUpsample", "0", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_imageUpsampleMaxSize = ri_Cvar_Get_NoComm( "r_imageUpsampleMaxSize", "1024", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_imageUpsampleType = ri_Cvar_Get_NoComm( "r_imageUpsampleType", "1", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_genNormalMaps = ri_Cvar_Get_NoComm( "r_genNormalMaps", "0", CVAR_ARCHIVE | CVAR_LATCH, "Disable/enable generating normal maps from diffuse maps" ); + + r_forceSun = ri_Cvar_Get_NoComm( "r_forceSun", "0", CVAR_CHEAT, "" ); + r_forceSunMapLightScale = ri_Cvar_Get_NoComm( "r_forceSunMapLightScale", "1.0", CVAR_CHEAT, "" ); + r_forceSunLightScale = ri_Cvar_Get_NoComm( "r_forceSunLightScale", "1.0", CVAR_CHEAT, "" ); + r_forceSunAmbientScale = ri_Cvar_Get_NoComm( "r_forceSunAmbientScale", "0.5", CVAR_CHEAT, "" ); + r_drawSunRays = ri_Cvar_Get_NoComm( "r_drawSunRays", "0", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_sunlightMode = ri_Cvar_Get_NoComm( "r_sunlightMode", "1", CVAR_ARCHIVE | CVAR_LATCH, "" ); + + r_sunShadows = ri_Cvar_Get_NoComm( "r_sunShadows", "1", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_shadowFilter = ri_Cvar_Get_NoComm( "r_shadowFilter", "1", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_shadowMapSize = ri_Cvar_Get_NoComm( "r_shadowMapSize", "1024", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_shadowCascadeZNear = ri_Cvar_Get_NoComm( "r_shadowCascadeZNear", "4", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_shadowCascadeZFar = ri_Cvar_Get_NoComm( "r_shadowCascadeZFar", "3072", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_shadowCascadeZBias = ri_Cvar_Get_NoComm( "r_shadowCascadeZBias", "-320", CVAR_ARCHIVE | CVAR_LATCH, "" ); + r_ignoreDstAlpha = ri_Cvar_Get_NoComm( "r_ignoreDstAlpha", "1", CVAR_ARCHIVE | CVAR_LATCH, "" ); + + // + // temporary latched variables that can only change over a restart + // + r_fullbright = ri_Cvar_Get_NoComm ("r_fullbright", "0", CVAR_LATCH|CVAR_CHEAT, "" ); + r_mapOverBrightBits = ri_Cvar_Get_NoComm ("r_mapOverBrightBits", "0", CVAR_LATCH, "" ); + r_intensity = ri_Cvar_Get_NoComm ("r_intensity", "1", CVAR_LATCH, "" ); + r_singleShader = ri_Cvar_Get_NoComm ("r_singleShader", "0", CVAR_CHEAT | CVAR_LATCH, "" ); + + // + // archived variables that can change at any time + // + r_lodCurveError = ri_Cvar_Get_NoComm( "r_lodCurveError", "250", CVAR_ARCHIVE|CVAR_CHEAT, "" ); + r_lodbias = ri_Cvar_Get_NoComm( "r_lodbias", "0", CVAR_ARCHIVE, "" ); + r_flares = ri_Cvar_Get_NoComm ("r_flares", "0", CVAR_ARCHIVE, "" ); + r_znear = ri_Cvar_Get_NoComm( "r_znear", "4", CVAR_CHEAT, "" ); + ri.Cvar_CheckRange( r_znear, 0.001f, 200, qfalse ); + r_autolodscalevalue = ri_Cvar_Get_NoComm( "r_autolodscalevalue", "0", CVAR_ROM, "" ); + r_zproj = ri_Cvar_Get_NoComm( "r_zproj", "64", CVAR_ARCHIVE, "" ); + r_stereoSeparation = ri_Cvar_Get_NoComm( "r_stereoSeparation", "64", CVAR_ARCHIVE, "" ); + r_ignoreGLErrors = ri_Cvar_Get_NoComm( "r_ignoreGLErrors", "1", CVAR_ARCHIVE, "" ); + r_fastsky = ri_Cvar_Get_NoComm( "r_fastsky", "0", CVAR_ARCHIVE, "" ); + r_inGameVideo = ri_Cvar_Get_NoComm( "r_inGameVideo", "1", CVAR_ARCHIVE, "" ); + r_drawSun = ri_Cvar_Get_NoComm( "r_drawSun", "0", CVAR_ARCHIVE, "" ); + r_dynamiclight = ri_Cvar_Get_NoComm( "r_dynamiclight", "1", CVAR_ARCHIVE, "" ); + r_finish = ri_Cvar_Get_NoComm ("r_finish", "0", CVAR_ARCHIVE, ""); + r_textureMode = ri_Cvar_Get_NoComm( "r_textureMode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE, "" ); + r_markcount = ri_Cvar_Get_NoComm( "r_markcount", "100", CVAR_ARCHIVE, "" ); + r_gamma = ri_Cvar_Get_NoComm( "r_gamma", "1", CVAR_ARCHIVE, "" ); + r_facePlaneCull = ri_Cvar_Get_NoComm ("r_facePlaneCull", "1", CVAR_ARCHIVE, "" ); + + r_ambientScale = ri_Cvar_Get_NoComm( "r_ambientScale", "0.6", CVAR_CHEAT, "" ); + r_directedScale = ri_Cvar_Get_NoComm( "r_directedScale", "1", CVAR_CHEAT, "" ); + + r_anaglyphMode = ri_Cvar_Get_NoComm("r_anaglyphMode", "0", CVAR_ARCHIVE, ""); + r_mergeMultidraws = ri_Cvar_Get_NoComm("r_mergeMultidraws", "1", CVAR_ARCHIVE, ""); + r_mergeLeafSurfaces = ri_Cvar_Get_NoComm("r_mergeLeafSurfaces", "1", CVAR_ARCHIVE, ""); + + // + // temporary variables that can change at any time + // + r_showImages = ri_Cvar_Get_NoComm( "r_showImages", "0", CVAR_TEMP, "" ); + + r_debugLight = ri_Cvar_Get_NoComm( "r_debuglight", "0", CVAR_TEMP, "" ); + r_debugSort = ri_Cvar_Get_NoComm( "r_debugSort", "0", CVAR_CHEAT, "" ); + r_printShaders = ri_Cvar_Get_NoComm( "r_printShaders", "0", 0, "" ); + r_saveFontData = ri_Cvar_Get_NoComm( "r_saveFontData", "0", 0, "" ); + + r_forceParallaxBias = ri_Cvar_Get_NoComm("r_forceParallaxBias", "0", CVAR_TEMP, ""); + ri.Cvar_CheckRange(r_forceParallaxBias, 0.0f, 1.0f, qfalse); + + r_nocurves = ri_Cvar_Get_NoComm ("r_nocurves", "0", CVAR_CHEAT, "" ); + r_drawworld = ri_Cvar_Get_NoComm ("r_drawworld", "1", CVAR_CHEAT, "" ); + r_drawfog = ri_Cvar_Get_NoComm("r_drawfog", "2", CVAR_CHEAT, ""); + r_lightmap = ri_Cvar_Get_NoComm ("r_lightmap", "0", 0, "" ); + r_portalOnly = ri_Cvar_Get_NoComm ("r_portalOnly", "0", CVAR_CHEAT, "" ); + + r_skipBackEnd = ri_Cvar_Get_NoComm ("r_skipBackEnd", "0", CVAR_CHEAT, ""); + + r_measureOverdraw = ri_Cvar_Get_NoComm( "r_measureOverdraw", "0", CVAR_CHEAT, "" ); + r_lodscale = ri_Cvar_Get_NoComm( "r_lodscale", "5", CVAR_CHEAT, "" ); + r_norefresh = ri_Cvar_Get_NoComm ("r_norefresh", "0", CVAR_CHEAT, ""); + r_drawentities = ri_Cvar_Get_NoComm ("r_drawentities", "1", CVAR_CHEAT, "" ); + r_ignore = ri_Cvar_Get_NoComm( "r_ignore", "1", CVAR_CHEAT, "" ); + r_nocull = ri_Cvar_Get_NoComm ("r_nocull", "0", CVAR_CHEAT, ""); + r_novis = ri_Cvar_Get_NoComm ("r_novis", "0", CVAR_CHEAT, ""); + r_showcluster = ri_Cvar_Get_NoComm ("r_showcluster", "0", CVAR_CHEAT, ""); + r_speeds = ri_Cvar_Get_NoComm ("r_speeds", "0", CVAR_CHEAT, ""); + r_verbose = ri_Cvar_Get_NoComm( "r_verbose", "0", CVAR_CHEAT, "" ); + r_logFile = ri_Cvar_Get_NoComm( "r_logFile", "0", CVAR_CHEAT, "" ); + r_debugSurface = ri_Cvar_Get_NoComm ("r_debugSurface", "0", CVAR_CHEAT, ""); + r_nobind = ri_Cvar_Get_NoComm ("r_nobind", "0", CVAR_CHEAT, ""); + r_showtris = ri_Cvar_Get_NoComm ("r_showtris", "0", CVAR_CHEAT, ""); + r_showsky = ri_Cvar_Get_NoComm ("r_showsky", "0", CVAR_CHEAT, ""); + r_shownormals = ri_Cvar_Get_NoComm ("r_shownormals", "0", CVAR_CHEAT, ""); + r_clear = ri_Cvar_Get_NoComm ("r_clear", "0", CVAR_CHEAT, ""); + r_offsetFactor = ri_Cvar_Get_NoComm( "r_offsetfactor", "-1", CVAR_CHEAT, "" ); + r_offsetUnits = ri_Cvar_Get_NoComm( "r_offsetunits", "-2", CVAR_CHEAT, "" ); + + r_shadowOffsetFactor = ri_Cvar_Get_NoComm("r_shadowOffsetFactor", "1.0", CVAR_CHEAT, ""); + r_shadowOffsetUnits = ri_Cvar_Get_NoComm("r_shadowOffsetUnits", "1.0", CVAR_CHEAT, ""); + + r_drawBuffer = ri_Cvar_Get_NoComm( "r_drawBuffer", "GL_BACK", CVAR_CHEAT, "" ); + r_lockpvs = ri_Cvar_Get_NoComm ("r_lockpvs", "0", CVAR_CHEAT, ""); + r_noportals = ri_Cvar_Get_NoComm ("r_noportals", "0", CVAR_CHEAT, ""); + r_shadows = ri_Cvar_Get_NoComm( "cg_shadows", "1", 0, "" ); + + r_marksOnTriangleMeshes = ri_Cvar_Get_NoComm("r_marksOnTriangleMeshes", "0", CVAR_ARCHIVE, ""); + + r_aviMotionJpegQuality = ri_Cvar_Get_NoComm("r_aviMotionJpegQuality", "90", CVAR_ARCHIVE, ""); + r_screenshotJpegQuality = ri_Cvar_Get_NoComm("r_screenshotJpegQuality", "90", CVAR_ARCHIVE, ""); + r_surfaceSprites = ri_Cvar_Get_NoComm("r_surfaceSprites", "1", CVAR_ARCHIVE, ""); + + r_aspectCorrectFonts = ri_Cvar_Get_NoComm( "r_aspectCorrectFonts", "0", CVAR_ARCHIVE, "" ); + r_maxpolys = ri_Cvar_Get_NoComm( "r_maxpolys", XSTRING( DEFAULT_MAX_POLYS ), 0, ""); + r_maxpolyverts = ri_Cvar_Get_NoComm( "r_maxpolyverts", XSTRING( DEFAULT_MAX_POLYVERTS ), 0, "" ); + + r_patchStitching = ri_Cvar_Get_NoComm("r_patchStitching", "1", CVAR_ARCHIVE, "Enable stitching of neighbouring patch surfaces" ); + /* + Ghoul2 Insert Start + */ +#ifdef _DEBUG + r_noPrecacheGLA = ri_Cvar_Get_NoComm( "r_noPrecacheGLA", "0", CVAR_CHEAT, "" ); +#endif + r_noServerGhoul2 = ri_Cvar_Get_NoComm( "r_noghoul2", "0", CVAR_CHEAT, "" ); + r_Ghoul2AnimSmooth = ri_Cvar_Get_NoComm( "r_ghoul2animsmooth", "0.3", CVAR_TEMP, "" ); + r_Ghoul2UnSqashAfterSmooth = ri_Cvar_Get_NoComm( "r_ghoul2unsqashaftersmooth", "1", CVAR_TEMP, "" ); + broadsword = ri_Cvar_Get_NoComm( "broadsword", "0", CVAR_ARCHIVE, "" ); + broadsword_kickbones = ri_Cvar_Get_NoComm( "broadsword_kickbones", "1", CVAR_TEMP, "" ); + broadsword_kickorigin = ri_Cvar_Get_NoComm( "broadsword_kickorigin", "1", CVAR_TEMP, "" ); + broadsword_dontstopanim = ri_Cvar_Get_NoComm( "broadsword_dontstopanim", "0", CVAR_TEMP, "" ); + broadsword_waitforshot = ri_Cvar_Get_NoComm( "broadsword_waitforshot", "0", CVAR_TEMP, "" ); + broadsword_playflop = ri_Cvar_Get_NoComm( "broadsword_playflop", "1", CVAR_TEMP, "" ); + broadsword_smallbbox = ri_Cvar_Get_NoComm( "broadsword_smallbbox", "0", CVAR_TEMP, "" ); + broadsword_extra1 = ri_Cvar_Get_NoComm( "broadsword_extra1", "0", CVAR_TEMP, "" ); + broadsword_extra2 = ri_Cvar_Get_NoComm( "broadsword_extra2", "0", CVAR_TEMP, "" ); + broadsword_effcorr = ri_Cvar_Get_NoComm( "broadsword_effcorr", "1", CVAR_TEMP, "" ); + broadsword_ragtobase = ri_Cvar_Get_NoComm( "broadsword_ragtobase", "2", CVAR_TEMP, "" ); + broadsword_dircap = ri_Cvar_Get_NoComm( "broadsword_dircap", "64", CVAR_TEMP, "" ); + /* + Ghoul2 Insert End + */ + + se_language = ri_Cvar_Get_NoComm ( "se_language", "english", CVAR_ARCHIVE | CVAR_NORESTART, "" ); +#ifdef JK2_MODE + sp_language = ri.Cvar_Get("sp_language", va("%d", SP_LANGUAGE_ENGLISH), CVAR_ARCHIVE | CVAR_NORESTART); +#endif + // added for SP + // @TODO add all cvars from vanilla + com_buildScript = ri.Cvar_Get("com_buildScript", "0", 0); + sv_mapname = ri.Cvar_Get("mapname", "nomap", CVAR_SERVERINFO | CVAR_ROM); + sv_mapChecksum = ri.Cvar_Get("sv_mapChecksum", "", CVAR_ROM); + r_modelpoolmegs = ri.Cvar_Get("r_modelpoolmegs", "20", CVAR_ARCHIVE); + if (ri.LowPhysicalMemory()) + { + ri.Cvar_Set("r_modelpoolmegs", "0"); + } + r_environmentMapping = ri.Cvar_Get("r_environmentMapping", "1", CVAR_ARCHIVE_ND); + + for ( size_t i = 0; i < numCommands; i++ ) + ri.Cmd_AddCommand( commands[i].cmd, commands[i].func ); +} + +void R_InitQueries(void) +{ + if (r_drawSunRays->integer) + qglGenQueries(ARRAY_LEN(tr.sunFlareQuery), tr.sunFlareQuery); +} + +void R_ShutDownQueries(void) +{ + if (r_drawSunRays->integer) + qglDeleteQueries(ARRAY_LEN(tr.sunFlareQuery), tr.sunFlareQuery); +} + +void RE_SetLightStyle (int style, int color); + +static void R_InitBackEndFrameData() +{ + GLuint timerQueries[MAX_GPU_TIMERS*MAX_FRAMES]; + qglGenQueries(MAX_GPU_TIMERS*MAX_FRAMES, timerQueries); + + GLuint ubos[MAX_FRAMES * MAX_SCENES]; + qglGenBuffers(MAX_FRAMES * MAX_SCENES, ubos); + + + for ( int i = 0; i < MAX_FRAMES; i++ ) + { + gpuFrame_t *frame = backEndData->frames + i; + const GLbitfield mapBits = GL_MAP_WRITE_BIT | GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT; + + for (byte j = 0; j < MAX_SCENES; j++) + { + size_t BUFFER_SIZE = j == 0 ? FRAME_UNIFORM_BUFFER_SIZE : FRAME_SCENE_UNIFORM_BUFFER_SIZE; + frame->ubo[j] = ubos[i * MAX_SCENES + j]; + frame->uboWriteOffset[j] = 0; + frame->uboSize[j] = BUFFER_SIZE; + qglBindBuffer(GL_UNIFORM_BUFFER, frame->ubo[j]); + glState.currentGlobalUBO = frame->ubo[j]; + + // TODO: persistently mapped UBOs + qglBufferData(GL_UNIFORM_BUFFER, BUFFER_SIZE, + nullptr, GL_DYNAMIC_DRAW); + } + + // TODO: persistently mapped UBOs + qglBufferData(GL_UNIFORM_BUFFER, FRAME_UNIFORM_BUFFER_SIZE, + nullptr, GL_DYNAMIC_DRAW); + + frame->dynamicVbo = R_CreateVBO(nullptr, FRAME_VERTEX_BUFFER_SIZE, + VBO_USAGE_DYNAMIC); + frame->dynamicVboCommitOffset = 0; + frame->dynamicVboWriteOffset = 0; + + frame->dynamicIbo = R_CreateIBO(nullptr, FRAME_INDEX_BUFFER_SIZE, + VBO_USAGE_DYNAMIC); + frame->dynamicIboCommitOffset = 0; + frame->dynamicIboWriteOffset = 0; + + if ( glRefConfig.immutableBuffers ) + { + R_BindVBO(frame->dynamicVbo); + frame->dynamicVboMemory = qglMapBufferRange(GL_ARRAY_BUFFER, 0, + frame->dynamicVbo->vertexesSize, mapBits); + + R_BindIBO(frame->dynamicIbo); + frame->dynamicIboMemory = qglMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 0, + frame->dynamicIbo->indexesSize, mapBits); + } + else + { + frame->dynamicVboMemory = nullptr; + frame->dynamicIboMemory = nullptr; + } + + for ( int j = 0; j < MAX_GPU_TIMERS; j++ ) + { + gpuTimer_t *timer = frame->timers + j; + timer->queryName = timerQueries[i*MAX_GPU_TIMERS + j]; + } + } + + backEndData->currentFrame = backEndData->frames; +} + +#ifdef _G2_GORE +static void R_InitGoreVao() +{ + tr.goreVBO = R_CreateVBO( + nullptr, + sizeof(g2GoreVert_t) * MAX_GORE_RECORDS * MAX_GORE_VERTS * MAX_FRAMES, + VBO_USAGE_DYNAMIC); + tr.goreVBO->offsets[ATTR_INDEX_POSITION] = offsetof(g2GoreVert_t, position); + tr.goreVBO->offsets[ATTR_INDEX_NORMAL] = offsetof(g2GoreVert_t, normal); + tr.goreVBO->offsets[ATTR_INDEX_TEXCOORD0] = offsetof(g2GoreVert_t, texCoords); + tr.goreVBO->offsets[ATTR_INDEX_BONE_INDEXES] = offsetof(g2GoreVert_t, bonerefs); + tr.goreVBO->offsets[ATTR_INDEX_BONE_WEIGHTS] = offsetof(g2GoreVert_t, weights); + tr.goreVBO->offsets[ATTR_INDEX_TANGENT] = offsetof(g2GoreVert_t, tangents); + + tr.goreVBO->strides[ATTR_INDEX_POSITION] = sizeof(g2GoreVert_t); + tr.goreVBO->strides[ATTR_INDEX_NORMAL] = sizeof(g2GoreVert_t); + tr.goreVBO->strides[ATTR_INDEX_TEXCOORD0] = sizeof(g2GoreVert_t); + tr.goreVBO->strides[ATTR_INDEX_BONE_INDEXES] = sizeof(g2GoreVert_t); + tr.goreVBO->strides[ATTR_INDEX_BONE_WEIGHTS] = sizeof(g2GoreVert_t); + tr.goreVBO->strides[ATTR_INDEX_TANGENT] = sizeof(g2GoreVert_t); + + tr.goreVBO->sizes[ATTR_INDEX_POSITION] = sizeof(vec3_t); + tr.goreVBO->sizes[ATTR_INDEX_NORMAL] = sizeof(uint32_t); + tr.goreVBO->sizes[ATTR_INDEX_TEXCOORD0] = sizeof(vec2_t); + tr.goreVBO->sizes[ATTR_INDEX_BONE_WEIGHTS] = sizeof(byte); + tr.goreVBO->sizes[ATTR_INDEX_BONE_INDEXES] = sizeof(byte); + tr.goreVBO->sizes[ATTR_INDEX_TANGENT] = sizeof(uint32_t); + + tr.goreIBO = R_CreateIBO( + nullptr, + sizeof(glIndex_t) * MAX_GORE_RECORDS * MAX_GORE_INDECIES * MAX_FRAMES, + VBO_USAGE_DYNAMIC); + + tr.goreIBOCurrentIndex = 0; + tr.goreVBOCurrentIndex = 0; + + GL_CheckErrors(); +} +#endif + +static void R_InitStaticConstants() +{ + const int alignment = glRefConfig.uniformBufferOffsetAlignment - 1; + size_t alignedBlockSize = 0; + + qglBindBuffer(GL_UNIFORM_BUFFER, tr.staticUbo); + qglBufferData( + GL_UNIFORM_BUFFER, + STATIC_UNIFORM_BUFFER_SIZE, + nullptr, + GL_STATIC_DRAW); + + // Setup static 2d camera data + EntityBlock entity2DBlock = {}; + entity2DBlock.fxVolumetricBase = -1.0f; + Matrix16Identity(entity2DBlock.modelMatrix); + tr.entity2DUboOffset = alignedBlockSize; + qglBufferSubData( + GL_UNIFORM_BUFFER, 0, sizeof(entity2DBlock), &entity2DBlock); + alignedBlockSize += (sizeof(EntityBlock) + alignment) & ~alignment; + + // Setup static 2d camera data + CameraBlock a2DCameraBlock = {}; + Matrix16Ortho( + 0.0f, + 640.0f, + 480.0f, + 0.0f, + 0.0f, + 1.0f, + a2DCameraBlock.viewProjectionMatrix); + + tr.camera2DUboOffset = alignedBlockSize; + qglBufferSubData( + GL_UNIFORM_BUFFER, tr.camera2DUboOffset, sizeof(a2DCameraBlock), &a2DCameraBlock); + alignedBlockSize += (sizeof(CameraBlock) + alignment) & ~alignment; + + // Setup static flare entity data + EntityBlock entityFlareBlock = {}; + entityFlareBlock.fxVolumetricBase = -1.0f; + Matrix16Identity(entityFlareBlock.modelMatrix); + + tr.entityFlareUboOffset = alignedBlockSize; + qglBufferSubData( + GL_UNIFORM_BUFFER, tr.entityFlareUboOffset, sizeof(entityFlareBlock), &entityFlareBlock); + alignedBlockSize += (sizeof(EntityBlock) + alignment) & ~alignment; + + // Setup static flare camera data + CameraBlock flareCameraBlock = {}; + Matrix16Ortho( + 0.0f, + glConfig.vidWidth, + glConfig.vidHeight, + 0.0f, + -99999.0f, + 99999.0f, + flareCameraBlock.viewProjectionMatrix); + + tr.cameraFlareUboOffset = alignedBlockSize; + qglBufferSubData( + GL_UNIFORM_BUFFER, tr.cameraFlareUboOffset, sizeof(flareCameraBlock), &flareCameraBlock); + alignedBlockSize += (sizeof(CameraBlock) + alignment) & ~alignment; + + // Setup default light block + LightsBlock lightsBlock = {}; + lightsBlock.numLights = 0; + + tr.defaultLightsUboOffset = alignedBlockSize; + qglBufferSubData( + GL_UNIFORM_BUFFER, tr.defaultLightsUboOffset, sizeof(lightsBlock), &lightsBlock); + alignedBlockSize += (sizeof(LightsBlock) + alignment) & ~alignment; + + // Setup default scene block + SceneBlock sceneBlock = {}; + sceneBlock.globalFogIndex = -1; + sceneBlock.currentTime = 0.1f; + sceneBlock.frameTime = 0.1f; + + tr.defaultSceneUboOffset = alignedBlockSize; + qglBufferSubData( + GL_UNIFORM_BUFFER, tr.defaultSceneUboOffset, sizeof(sceneBlock), &sceneBlock); + alignedBlockSize += (sizeof(SceneBlock) + alignment) & ~alignment; + + // Setup default fogs block + FogsBlock fogsBlock = {}; + fogsBlock.numFogs = 0; + tr.defaultFogsUboOffset = alignedBlockSize; + qglBufferSubData( + GL_UNIFORM_BUFFER, tr.defaultFogsUboOffset, sizeof(fogsBlock), &fogsBlock); + alignedBlockSize += (sizeof(FogsBlock) + alignment) & ~alignment; + + // Setup default shader instance block + ShaderInstanceBlock shaderInstanceBlock = {}; + tr.defaultShaderInstanceUboOffset = alignedBlockSize; + qglBufferSubData( + GL_UNIFORM_BUFFER, tr.defaultShaderInstanceUboOffset, sizeof(shaderInstanceBlock), &shaderInstanceBlock); + alignedBlockSize += (sizeof(ShaderInstanceBlock) + alignment) & ~alignment; + + qglBindBuffer(GL_UNIFORM_BUFFER, NULL); + glState.currentGlobalUBO = -1; + + GL_CheckErrors(); +} + +static void R_ShutdownBackEndFrameData() +{ + if ( !backEndData ) + return; + + for ( int i = 0; i < MAX_FRAMES; i++ ) + { + gpuFrame_t *frame = backEndData->frames + i; + + if (frame->sync) + { + qglDeleteSync(frame->sync); + frame->sync = NULL; + } + + qglDeleteBuffers(MAX_SCENES, frame->ubo); + + if ( glRefConfig.immutableBuffers ) + { + R_BindVBO(frame->dynamicVbo); + R_BindIBO(frame->dynamicIbo); + qglUnmapBuffer(GL_ARRAY_BUFFER); + qglUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); + } + + for ( int j = 0; j < MAX_GPU_TIMERS; j++ ) + { + gpuTimer_t *timer = frame->timers + j; + qglDeleteQueries(1, &timer->queryName); + } + } +} + +// need to do this hackery so ghoul2 doesn't crash the game because of ITS hackery... +// +void R_ClearStuffToStopGhoul2CrashingThings(void) +{ + memset(&tr, 0, sizeof(tr)); +} + +static bool r_inited = false; +/* +=============== +R_Init +=============== +*/ +void R_Init( void ) { + byte *ptr; + int i; + + if (r_inited) + return; + + ri.Printf( PRINT_ALL, "----- R_Init -----\n" ); + + // clear all our internal state + Com_Memset( &tr, 0, sizeof( tr ) ); + Com_Memset( &backEnd, 0, sizeof( backEnd ) ); + Com_Memset( &tess, 0, sizeof( tess ) ); + + + // + // init function tables + // + for ( i = 0; i < FUNCTABLE_SIZE; i++ ) + { + tr.sinTable[i] = sin( DEG2RAD( i * 360.0f / ( ( float ) ( FUNCTABLE_SIZE - 1 ) ) ) ); + tr.squareTable[i] = ( i < FUNCTABLE_SIZE/2 ) ? 1.0f : -1.0f; + tr.sawToothTable[i] = (float)i / FUNCTABLE_SIZE; + tr.inverseSawToothTable[i] = 1.0f - tr.sawToothTable[i]; + + if ( i < FUNCTABLE_SIZE / 2 ) + { + if ( i < FUNCTABLE_SIZE / 4 ) + { + tr.triangleTable[i] = ( float ) i / ( FUNCTABLE_SIZE / 4 ); + } + else + { + tr.triangleTable[i] = 1.0f - tr.triangleTable[i-FUNCTABLE_SIZE / 4]; + } + } + else + { + tr.triangleTable[i] = -tr.triangleTable[i-FUNCTABLE_SIZE/2]; + } + } + + R_InitFogTable(); + + R_ImageLoader_Init(); + R_NoiseInit(); + R_Register(); + + max_polys = Q_min( r_maxpolys->integer, DEFAULT_MAX_POLYS ); + max_polyverts = Q_min( r_maxpolyverts->integer, DEFAULT_MAX_POLYVERTS ); + + ptr = (byte*)Hunk_Alloc( + sizeof( *backEndData ) + + sizeof(srfPoly_t) * max_polys + + sizeof(polyVert_t) * max_polyverts + + sizeof(Allocator) + + PER_FRAME_MEMORY_BYTES, + h_low); + + backEndData = (backEndData_t *)ptr; + ptr = (byte *)(backEndData + 1); + + backEndData->polys = (srfPoly_t *)ptr; + ptr += sizeof(*backEndData->polys) * max_polys; + + backEndData->polyVerts = (polyVert_t *)ptr; + ptr += sizeof(*backEndData->polyVerts) * max_polyverts; + + backEndData->perFrameMemory = new(ptr) Allocator(ptr + sizeof(*backEndData->perFrameMemory), PER_FRAME_MEMORY_BYTES); + + R_InitNextFrame(); + + for ( int i = 0; i < MAX_LIGHT_STYLES; i++ ) + { + RE_SetLightStyle (i, -1); + } + + R_InitImagesPool(); + + InitOpenGL(); + + R_InitGPUBuffers(); + + R_InitStaticConstants(); + R_InitBackEndFrameData(); + R_InitImages(); + +#ifdef _G2_GORE + R_InitGoreVao(); +#endif + + FBO_Init(); + + GLSL_LoadGPUShaders(); + + R_InitShaders(qfalse); + + R_InitSkins(); + + R_InitFonts(); + + R_ModelInit(); + + R_InitDecals(); + + R_InitQueries(); + + R_InitWeatherSystem(); + +#if defined(_DEBUG) + GLenum err = qglGetError(); + if ( err != GL_NO_ERROR ) + ri.Printf( PRINT_ALL, "glGetError() = 0x%x\n", err ); +#endif + + RestoreGhoul2InfoArray(); + + // print info + GfxInfo_f(); + r_inited = true; + ri.Printf( PRINT_ALL, "----- finished R_Init -----\n" ); +} + +/* +=============== +RE_Shutdown +=============== +*/ +void RE_Shutdown( qboolean destroyWindow, qboolean restarting ) { + + ri.Printf( PRINT_ALL, "RE_Shutdown( %i )\n", destroyWindow ); + + for ( size_t i = 0; i < numCommands; i++ ) + ri.Cmd_RemoveCommand( commands[i].cmd ); + + // Flush here to make sure all the fences are processed + qglFlush(); + + R_IssuePendingRenderCommands(); + + R_ShutdownBackEndFrameData(); + + R_ShutdownWeatherSystem(); + + R_ShutdownFonts(); + + if (r_inited) + { + R_ShutDownQueries(); + FBO_Shutdown(); + R_DeleteTextures(); + R_DestroyGPUBuffers(); + GLSL_ShutdownGPUShaders(); + } + + if (destroyWindow && restarting && tr.registered) + { + ri.Z_Free((void *)glConfig.extensions_string); + ri.Z_Free((void *)glConfigExt.originalExtensionString); + + qglDeleteVertexArrays(1, &tr.globalVao); + SaveGhoul2InfoArray(); + } + + // shut down platform specific OpenGL stuff + if ( destroyWindow ) { + ri.WIN_Shutdown(); + } + + tr.registered = qfalse; + r_inited = false; + backEndData = NULL; +} + +/* +============= +RE_EndRegistration + +Touch all images to make sure they are resident +============= +*/ +void RE_EndRegistration( void ) { + R_IssuePendingRenderCommands(); + /* + if (!ri.Sys_LowPhysicalMemory()) { + RB_ShowImages(); + } + */ +} + +// HACK +extern qboolean gG2_GBMNoReconstruct; +extern qboolean gG2_GBMUseSPMethod; +static void G2API_BoltMatrixReconstruction( qboolean reconstruct ) { gG2_GBMNoReconstruct = (qboolean)!reconstruct; } +static void G2API_BoltMatrixSPMethod( qboolean spMethod ) { gG2_GBMUseSPMethod = spMethod; } + +static float GetDistanceCull( void ) { return tr.distanceCull; } + +extern void R_SVModelInit( void ); //tr_model.cpp + +static void GetRealRes( int *w, int *h ) { + *w = glConfig.vidWidth; + *h = glConfig.vidHeight; +} + +// STUBS, REPLACEME +qboolean stub_InitializeWireframeAutomap() { return qtrue; } + +void RE_GetLightStyle(int style, color4ub_t color) +{ + if (style >= MAX_LIGHT_STYLES) + { + Com_Error( ERR_FATAL, "RE_GetLightStyle: %d is out of range", style ); + return; + } + + byteAlias_t *baDest = (byteAlias_t *)&color, *baSource = (byteAlias_t *)&styleColors[style]; + baDest->i = baSource->i; +} + +void RE_SetLightStyle(int style, int color) +{ + if (style >= MAX_LIGHT_STYLES) + { + Com_Error( ERR_FATAL, "RE_SetLightStyle: %d is out of range", style ); + return; + } + + byteAlias_t *ba = (byteAlias_t *)&styleColors[style]; + if ( ba->i != color) { + ba->i = color; + } +} + +void RE_GetBModelVerts(int bmodelIndex, vec3_t *verts, vec3_t normal); + + +void stub_RE_AddWeatherZone ( vec3_t mins, vec3_t maxs ) {} // Intentionally left blank. Rend2 reads the zones manually on bsp load +static void RE_SetRefractionProperties ( float distortionAlpha, float distortionStretch, qboolean distortionPrePost, qboolean distortionNegate ) { } + +void C_LevelLoadBegin(const char *psMapName, ForceReload_e eForceReload, qboolean bAllowScreenDissolve) +{ + static char sPrevMapName[MAX_QPATH]={0}; + bool bDeleteModels = eForceReload == eForceReload_MODELS || eForceReload == eForceReload_ALL; + + if( bDeleteModels ) + CModelCache->DeleteAll(); + else if( ri.Cvar_VariableIntegerValue( "sv_pure" ) ) + CModelCache->DumpNonPure(); + + tr.numBSPModels = 0; + + /* If we're switching to the same level, don't increment current level */ + if (Q_stricmp( psMapName,sPrevMapName )) + { + Q_strncpyz( sPrevMapName, psMapName, sizeof(sPrevMapName) ); + tr.currentLevel++; + } +} + +int C_GetLevel( void ) +{ + return tr.currentLevel; +} + +void C_LevelLoadEnd( void ) +{ +#ifndef REND2_SP + CModelCache->LevelLoadEnd(qfalse); + ri.SND_RegisterAudio_LevelLoadEnd(qfalse); + ri.S_RestartMusic(); +#else + CModelCache->LevelLoadEnd(qfalse); + + ri.SND_RegisterAudio_LevelLoadEnd(qfalse); + + if (gbAllowScreenDissolve) + { + RE_InitDissolve(qfalse); + } + + ri.S_RestartMusic(); + + *(ri.gbAlreadyDoingLoad()) = qfalse; +#endif // REND2_SP +} + +extern void RE_GetModelBounds(refEntity_t *refEnt, vec3_t bounds1, vec3_t bounds2); +extern void G2API_AnimateG2ModelsRag(CGhoul2Info_v &ghoul2, int AcurrentTime, CRagDollUpdateParams *params); +extern qboolean G2API_GetRagBonePos(CGhoul2Info_v &ghoul2, const char *boneName, vec3_t pos, vec3_t entAngles, vec3_t entPos, vec3_t entScale); +extern qboolean G2API_RagEffectorKick(CGhoul2Info_v &ghoul2, const char *boneName, vec3_t velocity); +extern qboolean G2API_RagForceSolve(CGhoul2Info_v &ghoul2, qboolean force); +extern qboolean G2API_SetBoneIKState(CGhoul2Info_v &ghoul2, int time, const char *boneName, int ikState, sharedSetBoneIKStateParams_t *params); +extern qboolean G2API_IKMove(CGhoul2Info_v &ghoul2, int time, sharedIKMoveParams_t *params); +extern qboolean G2API_RagEffectorGoal(CGhoul2Info_v &ghoul2, const char *boneName, vec3_t pos); +extern qboolean G2API_RagPCJGradientSpeed(CGhoul2Info_v &ghoul2, const char *boneName, const float speed); +extern qboolean G2API_RagPCJConstraint(CGhoul2Info_v &ghoul2, const char *boneName, vec3_t min, vec3_t max); +extern void G2API_SetRagDoll(CGhoul2Info_v &ghoul2, CRagDollParams *parms); +#ifdef G2_PERFORMANCE_ANALYSIS +extern void G2Time_ResetTimers(void); +extern void G2Time_ReportTimers(void); +#endif + +#ifdef JK2_MODE +unsigned int AnyLanguage_ReadCharFromString_JK2(char **text, qboolean *pbIsTrailingPunctuation) { + return AnyLanguage_ReadCharFromString(text, pbIsTrailingPunctuation); +} +#endif + +/* +@@@@@@@@@@@@@@@@@@@@@ +GetRefAPI + +@@@@@@@@@@@@@@@@@@@@@ +*/ +extern "C" { +Q_EXPORT refexport_t* QDECL GetRefAPI ( int apiVersion, refimport_t *rimp ) { + static refexport_t re; + + assert( rimp ); + ri = *rimp; + + Com_Memset( &re, 0, sizeof( re ) ); + + if ( apiVersion != REF_API_VERSION ) { + ri.Printf(PRINT_ALL, "Mismatched REF_API_VERSION: expected %i, got %i\n", + REF_API_VERSION, apiVersion ); + return NULL; + } + + // the RE_ functions are Renderer Entry points + + re.Shutdown = RE_Shutdown; + + re.BeginRegistration = RE_BeginRegistration; + re.RegisterModel = RE_RegisterModel; + re.RegisterSkin = RE_RegisterSkin; + re.GetAnimationCFG = RE_GetAnimationCFG; + re.RegisterShader = RE_RegisterShader; + re.RegisterShaderNoMip = RE_RegisterShaderNoMip; + re.LoadWorld = RE_LoadWorldMap; + re.R_LoadImage = R_LoadImage; + + re.RegisterMedia_LevelLoadBegin = C_LevelLoadBegin; + re.RegisterMedia_LevelLoadEnd = C_LevelLoadEnd; + re.RegisterMedia_GetLevel = C_GetLevel; + re.RegisterImages_LevelLoadEnd = C_Images_LevelLoadEnd; + re.RegisterModels_LevelLoadEnd = C_Models_LevelLoadEnd; + + re.SetWorldVisData = RE_SetWorldVisData; + + re.EndRegistration = RE_EndRegistration; + + re.ClearScene = RE_ClearScene; + //re.ClearDecals = RE_ClearDecals; + re.AddRefEntityToScene = RE_AddRefEntityToScene; + //re.AddMiniRefEntityToScene = RE_AddMiniRefEntityToScene; + re.AddPolyToScene = RE_AddPolyToScene; + re.AddLightToScene = RE_AddLightToScene; + //re.AddDecalToScene = RE_AddDecalToScene; + //re.LightForPoint = R_LightForPoint; + re.RenderScene = RE_RenderScene; + //re.AddAdditiveLightToScene = RE_AddAdditiveLightToScene; + re.GetLighting = RE_GetLighting; + + re.SetColor = RE_SetColor; + re.DrawStretchPic = RE_StretchPic; + re.DrawRotatePic = RE_RotatePic; + re.DrawRotatePic2 = RE_RotatePic2; + re.LAGoggles = RE_LAGoggles; + re.Scissor = RE_Scissor; + + re.DrawStretchRaw = RE_StretchRaw; + re.UploadCinematic = RE_UploadCinematic; + + re.BeginFrame = RE_BeginFrame; + re.EndFrame = RE_EndFrame; + + re.ProcessDissolve = RE_ProcessDissolve; + re.InitDissolve = RE_InitDissolve; + re.GetScreenShot = RE_GetScreenShot; + +#ifdef JK2_MODE + re.SaveJPGToBuffer = RE_SaveJPGToBuffer; + re.LoadJPGFromBuffer = LoadJPGFromBuffer; +#endif + re.TempRawImage_ReadFromFile = RE_TempRawImage_ReadFromFile; + re.TempRawImage_CleanUp = RE_TempRawImage_CleanUp; + + re.MarkFragments = R_MarkFragments; + re.LerpTag = R_LerpTag; + re.ModelBounds = R_ModelBounds; + re.GetLightStyle = RE_GetLightStyle; + re.SetLightStyle = RE_SetLightStyle; + re.GetBModelVerts = RE_GetBModelVerts; + re.WorldEffectCommand = RE_WorldEffectCommand; + re.GetModelBounds = RE_GetModelBounds; + + re.SVModelInit = R_SVModelInit; + + re.RegisterFont = RE_RegisterFont; + re.Font_HeightPixels = RE_Font_HeightPixels; + re.Font_StrLenPixels = RE_Font_StrLenPixels; + re.Font_DrawString = RE_Font_DrawString; + re.Font_StrLenChars = RE_Font_StrLenChars; + re.Language_IsAsian = Language_IsAsian; + re.Language_UsesSpaces = Language_UsesSpaces; + re.AnyLanguage_ReadCharFromString = AnyLanguage_ReadCharFromString; +#ifdef JK2_MODE + re.AnyLanguage_ReadCharFromString2 = AnyLanguage_ReadCharFromString_JK2; +#endif + + re.R_InitWorldEffects = stub_R_InitWorldEffects; + re.R_ClearStuffToStopGhoul2CrashingThings = R_ClearStuffToStopGhoul2CrashingThings; + re.R_inPVS = R_inPVS; + + re.tr_distortionAlpha = stub_get_tr_distortionAlpha; + re.tr_distortionStretch = stub_get_tr_distortionStretch; + re.tr_distortionPrePost = stub_get_tr_distortionPrePost; + re.tr_distortionNegate = stub_get_tr_distortionNegate; + + //re.InitializeWireframeAutomap = stub_InitializeWireframeAutomap; // MP + re.GetWindVector = R_GetWindVector; + re.GetWindGusting = R_GetWindGusting; + re.IsOutside = R_IsOutside; + re.IsOutsideCausingPain = R_IsOutsideCausingPain; + re.GetChanceOfSaberFizz = R_GetChanceOfSaberFizz; + re.IsShaking = R_IsShaking; + re.AddWeatherZone = stub_RE_AddWeatherZone; + re.SetTempGlobalFogColor = stub_R_SetTempGlobalFogColor; + + re.SetRangedFog = RE_SetRangedFog; + //re.GetDistanceCull = GetDistanceCull; // MP + //re.GetRealRes = GetRealRes; // MP + + re.TheGhoul2InfoArray = TheGhoul2InfoArray; + //re.GetEntityToken = R_GetEntityToken; //MP only, but need this for cubemaps... + + re.G2API_AddBolt = G2API_AddBolt; + re.G2API_AddBoltSurfNum = G2API_AddBoltSurfNum; + re.G2API_AddSurface = G2API_AddSurface; + re.G2API_AnimateG2Models = G2API_AnimateG2ModelsRag; + re.G2API_AttachEnt = G2API_AttachEnt; + re.G2API_AttachG2Model = G2API_AttachG2Model; + re.G2API_CollisionDetect = G2API_CollisionDetect; + re.G2API_CleanGhoul2Models = G2API_CleanGhoul2Models; + re.G2API_CopyGhoul2Instance = G2API_CopyGhoul2Instance; + re.G2API_DetachEnt = G2API_DetachEnt; + re.G2API_DetachG2Model = G2API_DetachG2Model; + re.G2API_GetAnimFileName = G2API_GetAnimFileName; + re.G2API_GetAnimFileNameIndex = G2API_GetAnimFileNameIndex; + re.G2API_GetAnimFileInternalNameIndex = G2API_GetAnimFileInternalNameIndex; + re.G2API_GetAnimIndex = G2API_GetAnimIndex; + re.G2API_GetAnimRange = G2API_GetAnimRange; + re.G2API_GetAnimRangeIndex = G2API_GetAnimRangeIndex; + re.G2API_GetBoneAnim = G2API_GetBoneAnim; + re.G2API_GetBoneAnimIndex = G2API_GetBoneAnimIndex; + re.G2API_GetBoneIndex = G2API_GetBoneIndex; + re.G2API_GetBoltMatrix = G2API_GetBoltMatrix; + re.G2API_GetGhoul2ModelFlags = G2API_GetGhoul2ModelFlags; + re.G2API_GetGLAName = G2API_GetGLAName; + re.G2API_GetParentSurface = G2API_GetParentSurface; + re.G2API_GetRagBonePos = G2API_GetRagBonePos; + re.G2API_GetSurfaceIndex = G2API_GetSurfaceIndex; + re.G2API_GetSurfaceName = G2API_GetSurfaceName; + re.G2API_GetSurfaceRenderStatus = G2API_GetSurfaceRenderStatus; + re.G2API_GetTime = G2API_GetTime; + re.G2API_GiveMeVectorFromMatrix = G2API_GiveMeVectorFromMatrix; + re.G2API_HaveWeGhoul2Models = G2API_HaveWeGhoul2Models; + re.G2API_IKMove = G2API_IKMove; + re.G2API_InitGhoul2Model = G2API_InitGhoul2Model; + re.G2API_IsPaused = G2API_IsPaused; + re.G2API_ListBones = G2API_ListBones; + re.G2API_ListSurfaces = G2API_ListSurfaces; + re.G2API_LoadGhoul2Models = G2API_LoadGhoul2Models; + re.G2API_LoadSaveCodeDestructGhoul2Info = G2API_LoadSaveCodeDestructGhoul2Info; + re.G2API_PauseBoneAnim = G2API_PauseBoneAnim; + re.G2API_PauseBoneAnimIndex = G2API_PauseBoneAnimIndex; + re.G2API_PrecacheGhoul2Model = G2API_PrecacheGhoul2Model; + re.G2API_RagEffectorGoal = G2API_RagEffectorGoal; + re.G2API_RagEffectorKick = G2API_RagEffectorKick; + re.G2API_RagForceSolve = G2API_RagForceSolve; + re.G2API_RagPCJConstraint = G2API_RagPCJConstraint; + re.G2API_RagPCJGradientSpeed = G2API_RagPCJGradientSpeed; + re.G2API_RemoveBolt = G2API_RemoveBolt; + re.G2API_RemoveBone = G2API_RemoveBone; + re.G2API_RemoveGhoul2Model = G2API_RemoveGhoul2Model; + re.G2API_RemoveSurface = G2API_RemoveSurface; + re.G2API_SaveGhoul2Models = G2API_SaveGhoul2Models; + re.G2API_SetAnimIndex = G2API_SetAnimIndex; + re.G2API_SetBoneAnim = G2API_SetBoneAnim; + re.G2API_SetBoneAnimIndex = G2API_SetBoneAnimIndex; + re.G2API_SetBoneAngles = G2API_SetBoneAngles; + re.G2API_SetBoneAnglesIndex = G2API_SetBoneAnglesIndex; + re.G2API_SetBoneAnglesMatrix = G2API_SetBoneAnglesMatrix; + re.G2API_SetBoneAnglesMatrixIndex = G2API_SetBoneAnglesMatrixIndex; + re.G2API_SetBoneIKState = G2API_SetBoneIKState; + re.G2API_SetGhoul2ModelFlags = G2API_SetGhoul2ModelFlags; + re.G2API_SetGhoul2ModelIndexes = G2API_SetGhoul2ModelIndexes; + re.G2API_SetLodBias = G2API_SetLodBias; + //G2EX(SetModelIndexes); + re.G2API_SetNewOrigin = G2API_SetNewOrigin; + re.G2API_SetRagDoll = G2API_SetRagDoll; + re.G2API_SetRootSurface = G2API_SetRootSurface; + re.G2API_SetShader = G2API_SetShader; + re.G2API_SetSkin = G2API_SetSkin; + re.G2API_SetSurfaceOnOff = G2API_SetSurfaceOnOff; + re.G2API_SetTime = G2API_SetTime; + re.G2API_StopBoneAnim = G2API_StopBoneAnim; + re.G2API_StopBoneAnimIndex = G2API_StopBoneAnimIndex; + re.G2API_StopBoneAngles = G2API_StopBoneAngles; + re.G2API_StopBoneAnglesIndex = G2API_StopBoneAnglesIndex; +#ifdef _G2_GORE + re.G2API_AddSkinGore = G2API_AddSkinGore; + re.G2API_ClearSkinGore = G2API_ClearSkinGore; + //re.G2API_GetNumGoreMarks = G2API_GetNumGoreMarks; // MP +#endif + +#ifdef G2_PERFORMANCE_ANALYSIS + re.G2Time_ReportTimers = G2Time_ReportTimers; + re.G2Time_ResetTimers = G2Time_ResetTimers; +#endif + + //Swap_Init(); + + return &re; +} +} diff --git a/code/rd-vanilla/G2_API.cpp b/code/rd-vanilla/G2_API.cpp index 09bc27edc2..d0cb10aece 100644 --- a/code/rd-vanilla/G2_API.cpp +++ b/code/rd-vanilla/G2_API.cpp @@ -2265,12 +2265,12 @@ bool G2_TestModelPointers(CGhoul2Info *ghlInfo) // returns true if the model is return ghlInfo->mValid; } -bool G2_SetupModelPointers(CGhoul2Info *ghlInfo) // returns true if the model is properly set up +qboolean G2_SetupModelPointers(CGhoul2Info *ghlInfo) // returns true if the model is properly set up { G2ERROR(ghlInfo,"NULL ghlInfo"); if (!ghlInfo) { - return false; + return qfalse; } ghlInfo->mValid=false; // G2WARNING(ghlInfo->mModelindex != -1,"Setup request on non-used info slot?"); @@ -2327,17 +2327,17 @@ bool G2_SetupModelPointers(CGhoul2Info *ghlInfo) // returns true if the model is ghlInfo->currentAnimModelSize=0; ghlInfo->aHeader=0; } - return ghlInfo->mValid; + return (qboolean)ghlInfo->mValid; } -bool G2_SetupModelPointers(CGhoul2Info_v &ghoul2) // returns true if any model is properly set up +qboolean G2_SetupModelPointers(CGhoul2Info_v &ghoul2) // returns true if any model is properly set up { - bool ret=false; + qboolean ret=qfalse; int i; for (i=0; ie.ghoul2); //entity is foo if it has a glm model handle but no ghoul2 pointer! - CGhoul2Info_v &ghoul2 = *ent->e.ghoul2; + CGhoul2Info_v &ghoul2 = *((CGhoul2Info_v *)ent->e.ghoul2); if (!G2_SetupModelPointers(ghoul2)) { diff --git a/code/rd-vanilla/tr_init.cpp b/code/rd-vanilla/tr_init.cpp index 13c72e66ee..b5423dc1b6 100644 --- a/code/rd-vanilla/tr_init.cpp +++ b/code/rd-vanilla/tr_init.cpp @@ -33,6 +33,7 @@ along with this program; if not, see . #include "tr_WorldEffects.h" glconfig_t glConfig; +glconfigExt_t glConfigExt; glstate_t glState; window_t window; @@ -677,10 +678,10 @@ static void GLimp_InitExtensions( void ) qglStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)ri.GL_GetProcAddress("glStencilOpSeparate"); if (qglStencilOpSeparate) { - glConfig.doStencilShadowsInOneDrawcall = qtrue; + glConfigExt.doStencilShadowsInOneDrawcall = qtrue; } #else - glConfig.doStencilShadowsInOneDrawcall = qtrue; + glConfigExt.doStencilShadowsInOneDrawcall = qtrue; #endif } diff --git a/code/rd-vanilla/tr_light.cpp b/code/rd-vanilla/tr_light.cpp index d176af56c5..aba59f7bce 100644 --- a/code/rd-vanilla/tr_light.cpp +++ b/code/rd-vanilla/tr_light.cpp @@ -227,7 +227,7 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) { } data = tr.world->lightGridData + *gridPos; - if ( data->styles[0] == LS_NONE ) + if ( data->styles[0] == LS_LSNONE ) { continue; // ignore samples in walls } @@ -243,7 +243,7 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent ) { for(j=0;jstyles[j] != LS_NONE) + if (data->styles[j] != LS_LSNONE) { const byte style= data->styles[j]; diff --git a/code/rd-vanilla/tr_local.h b/code/rd-vanilla/tr_local.h index c9e745aacd..9ded5e3de3 100644 --- a/code/rd-vanilla/tr_local.h +++ b/code/rd-vanilla/tr_local.h @@ -832,7 +832,7 @@ Ghoul2 Insert End void R_ModelInit (void); model_t *R_GetModelByHandle( qhandle_t hModel ); -void R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFrame, +int R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFrame, float frac, const char *tagName ); void R_ModelBounds( qhandle_t handle, vec3_t mins, vec3_t maxs ); @@ -1066,6 +1066,16 @@ typedef struct { float distanceCull; } trGlobals_t; +struct glconfigExt_t +{ + glconfig_t *glConfig; + + qboolean textureFilterAnisotropicAvailable; + qboolean doGammaCorrectionWithShaders; + qboolean doStencilShadowsInOneDrawcall; + const char *originalExtensionString; +}; + int R_Images_StartIteration(void); image_t *R_Images_GetNextIteration(void); void R_Images_Clear(void); @@ -1076,6 +1086,7 @@ void R_Images_DeleteImage(image_t *pImage); extern backEndState_t backEnd; extern trGlobals_t tr; extern glconfig_t glConfig; // outside of TR since it shouldn't be cleared during ref re-init +extern glconfigExt_t glConfigExt; extern glstate_t glState; // outside of TR since it shouldn't be cleared during ref re-init extern window_t window; @@ -1555,7 +1566,7 @@ void R_InitNextFrame( void ); void RE_ClearScene( void ); void RE_AddRefEntityToScene( const refEntity_t *ent ); -void RE_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts ); +void RE_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts, int numPolys ); void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b ); void RE_RenderScene( const refdef_t *fd ); diff --git a/code/rd-vanilla/tr_model.cpp b/code/rd-vanilla/tr_model.cpp index a6d5bc7b34..97ddb3dc85 100644 --- a/code/rd-vanilla/tr_model.cpp +++ b/code/rd-vanilla/tr_model.cpp @@ -1118,7 +1118,7 @@ static md3Tag_t *R_GetTag( md3Header_t *mod, int frame, const char *tagName ) { R_LerpTag ================ */ -void R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFrame, +int R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFrame, float frac, const char *tagName ) { md3Tag_t *start, *finish; int i; @@ -1135,13 +1135,13 @@ void R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFra { AxisClear( tag->axis ); VectorClear( tag->origin ); - return; + return qfalse; } if ( !start || !finish ) { AxisClear( tag->axis ); VectorClear( tag->origin ); - return; + return qfalse; } frontLerp = frac; @@ -1156,6 +1156,7 @@ void R_LerpTag( orientation_t *tag, qhandle_t handle, int startFrame, int endFra VectorNormalize( tag->axis[0] ); VectorNormalize( tag->axis[1] ); VectorNormalize( tag->axis[2] ); + return qtrue; } diff --git a/code/rd-vanilla/tr_scene.cpp b/code/rd-vanilla/tr_scene.cpp index d0b6b54977..ff78895241 100644 --- a/code/rd-vanilla/tr_scene.cpp +++ b/code/rd-vanilla/tr_scene.cpp @@ -116,9 +116,9 @@ RE_AddPolyToScene ===================== */ -void RE_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts ) { +void RE_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts, int numPolys ) { srfPoly_t *poly; - int i; + int i, j; int fogIndex = 0; fog_t *fog; vec3_t bounds[2]; @@ -134,67 +134,70 @@ void RE_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *vert return; } - if ( r_numpolyverts + numVerts >= MAX_POLYVERTS || r_numpolys >= MAX_POLYS ) { - /* - NOTE TTimo this was initially a PRINT_WARNING - but it happens a lot with high fighting scenes and particles - since we don't plan on changing the const and making for room for those effects - simply cut this message to developer only - */ - ri.Printf( PRINT_DEVELOPER, S_COLOR_YELLOW "WARNING: RE_AddPolyToScene: r_max_polys or r_max_polyverts reached\n"); - return; - } + for (j = 0; j < numPolys; j++) { + if (r_numpolyverts + numVerts >= MAX_POLYVERTS || r_numpolys >= MAX_POLYS) { + /* + NOTE TTimo this was initially a PRINT_WARNING + but it happens a lot with high fighting scenes and particles + since we don't plan on changing the const and making for room for those effects + simply cut this message to developer only + */ + ri.Printf(PRINT_DEVELOPER, S_COLOR_YELLOW "WARNING: RE_AddPolyToScene: r_max_polys or r_max_polyverts reached\n"); + return; + } + + poly = &backEndData->polys[r_numpolys]; + poly->surfaceType = SF_POLY; + poly->hShader = hShader; + poly->numVerts = numVerts; + poly->verts = &backEndData->polyVerts[r_numpolyverts]; + + memcpy( poly->verts, &verts[numVerts*j], numVerts * sizeof( *verts ) ); + r_numpolys++; + r_numpolyverts += numVerts; - poly = &backEndData->polys[r_numpolys]; - poly->surfaceType = SF_POLY; - poly->hShader = hShader; - poly->numVerts = numVerts; - poly->verts = &backEndData->polyVerts[r_numpolyverts]; - - memcpy( poly->verts, verts, numVerts * sizeof( *verts ) ); - r_numpolys++; - r_numpolyverts += numVerts; - - // see if it is in a fog volume - if ( !tr.world || tr.world->numfogs == 1) { - fogIndex = 0; - } else { - // find which fog volume the poly is in - VectorCopy( poly->verts[0].xyz, bounds[0] ); - VectorCopy( poly->verts[0].xyz, bounds[1] ); - for ( i = 1 ; i < poly->numVerts ; i++ ) { - AddPointToBounds( poly->verts[i].xyz, bounds[0], bounds[1] ); + // see if it is in a fog volume + if (!tr.world || tr.world->numfogs == 1) { + fogIndex = 0; } - for ( int fI = 1 ; fI < tr.world->numfogs ; fI++ ) { - fog = &tr.world->fogs[fI]; - if ( bounds[0][0] >= fog->bounds[0][0] - && bounds[0][1] >= fog->bounds[0][1] - && bounds[0][2] >= fog->bounds[0][2] - && bounds[1][0] <= fog->bounds[1][0] - && bounds[1][1] <= fog->bounds[1][1] - && bounds[1][2] <= fog->bounds[1][2] ) - {//completely in this one - fogIndex = fI; - break; + else { + // find which fog volume the poly is in + VectorCopy(poly->verts[0].xyz, bounds[0]); + VectorCopy(poly->verts[0].xyz, bounds[1]); + for (i = 1; i < poly->numVerts; i++) { + AddPointToBounds(poly->verts[i].xyz, bounds[0], bounds[1]); } - else if ( ( bounds[0][0] >= fog->bounds[0][0] && bounds[0][1] >= fog->bounds[0][1] && bounds[0][2] >= fog->bounds[0][2] && - bounds[0][0] <= fog->bounds[1][0] && bounds[0][1] <= fog->bounds[1][1] && bounds[0][2] <= fog->bounds[1][2]) || - ( bounds[1][0] >= fog->bounds[0][0] && bounds[1][1] >= fog->bounds[0][1] && bounds[1][2] >= fog->bounds[0][2] && - bounds[1][0] <= fog->bounds[1][0] && bounds[1][1] <= fog->bounds[1][1] && bounds[1][2] <= fog->bounds[1][2] ) ) - {//partially in this one - if ( tr.refdef.fogIndex == fI || R_FogParmsMatch( tr.refdef.fogIndex, fI ) ) - {//take new one only if it's the same one that the viewpoint is in + for (int fI = 1; fI < tr.world->numfogs; fI++) { + fog = &tr.world->fogs[fI]; + if (bounds[0][0] >= fog->bounds[0][0] + && bounds[0][1] >= fog->bounds[0][1] + && bounds[0][2] >= fog->bounds[0][2] + && bounds[1][0] <= fog->bounds[1][0] + && bounds[1][1] <= fog->bounds[1][1] + && bounds[1][2] <= fog->bounds[1][2]) + {//completely in this one fogIndex = fI; break; } - else if ( !fogIndex ) - {//didn't find one yet, so use this one - fogIndex = fI; + else if ((bounds[0][0] >= fog->bounds[0][0] && bounds[0][1] >= fog->bounds[0][1] && bounds[0][2] >= fog->bounds[0][2] && + bounds[0][0] <= fog->bounds[1][0] && bounds[0][1] <= fog->bounds[1][1] && bounds[0][2] <= fog->bounds[1][2]) || + (bounds[1][0] >= fog->bounds[0][0] && bounds[1][1] >= fog->bounds[0][1] && bounds[1][2] >= fog->bounds[0][2] && + bounds[1][0] <= fog->bounds[1][0] && bounds[1][1] <= fog->bounds[1][1] && bounds[1][2] <= fog->bounds[1][2])) + {//partially in this one + if (tr.refdef.fogIndex == fI || R_FogParmsMatch(tr.refdef.fogIndex, fI)) + {//take new one only if it's the same one that the viewpoint is in + fogIndex = fI; + break; + } + else if (!fogIndex) + {//didn't find one yet, so use this one + fogIndex = fI; + } } } } + poly->fogIndex = fogIndex; } - poly->fogIndex = fogIndex; } @@ -217,7 +220,13 @@ void RE_AddRefEntityToScene( const refEntity_t *ent ) { #endif return; } - if ( ent->reType < 0 || ent->reType >= RT_MAX_REF_ENTITY_TYPE ) { + + if (ent->reType == RT_ENT_CHAIN) + { //minirefents must die. + return; + } + + if ( (int)ent->reType < 0 || ent->reType >= RT_MAX_SP_REF_ENTITY_TYPE || ent->reType == RT_MAX_MP_REF_ENTITY_TYPE ) { Com_Error( ERR_DROP, "RE_AddRefEntityToScene: bad reType %i", ent->reType ); } @@ -228,6 +237,38 @@ void RE_AddRefEntityToScene( const refEntity_t *ent ) { } +/************************************************************************************************ + * RE_AddMiniRefEntityToScene * + * Adds a mini ref ent to the scene. If the input parameter is null, it signifies the end * + * of the chain. Otherwise, if there is a valid chain parent, it will be added to that. * + * If there is no parent, it will be added as a regular ref ent. * + * * + * Input * + * ent: the mini ref ent to be added * + * * + * Output / Return * + * none * + * * + ************************************************************************************************/ +void RE_AddMiniRefEntityToScene(const miniRefEntity_t *ent) +{ + if (!tr.registered) + { + return; + } + if (!ent) + { + return; + } + + refEntity_t tempEnt; + + memcpy(&tempEnt, ent, sizeof(*ent)); + memset(((char *)&tempEnt) + sizeof(*ent), 0, sizeof(tempEnt) - sizeof(*ent)); + RE_AddRefEntityToScene(&tempEnt); +} + + /* ===================== RE_AddLightToScene diff --git a/code/rd-vanilla/tr_shader.cpp b/code/rd-vanilla/tr_shader.cpp index 8991044919..abf8ec4c9b 100644 --- a/code/rd-vanilla/tr_shader.cpp +++ b/code/rd-vanilla/tr_shader.cpp @@ -91,9 +91,9 @@ const int lightmapsFullBright[MAXLIGHTMAPS] = const byte stylesDefault[MAXLIGHTMAPS] = { LS_NORMAL, - LS_NONE, - LS_NONE, - LS_NONE + LS_LSNONE, + LS_LSNONE, + LS_LSNONE }; static void ClearGlobalShader(void) diff --git a/code/rd-vanilla/tr_shadows.cpp b/code/rd-vanilla/tr_shadows.cpp index c0331e9763..4e415e9d84 100644 --- a/code/rd-vanilla/tr_shadows.cpp +++ b/code/rd-vanilla/tr_shadows.cpp @@ -350,7 +350,7 @@ void RB_DoShadowTessEnd( vec3_t lightPos ) qglDepthFunc(GL_LESS); //now using the Carmack Reverse -rww - if (glConfig.doStencilShadowsInOneDrawcall) + if (glConfigExt.doStencilShadowsInOneDrawcall) { GL_Cull(CT_TWO_SIDED); qglStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_KEEP); diff --git a/code/rd-vanilla/tr_subs.cpp b/code/rd-vanilla/tr_subs.cpp index c52bba0982..991dbab650 100644 --- a/code/rd-vanilla/tr_subs.cpp +++ b/code/rd-vanilla/tr_subs.cpp @@ -79,7 +79,7 @@ void Com_DPrintf(const char *format, ...) // ZONE void *R_Malloc( int iSize, memtag_t eTag, qboolean bZeroit ) { - return ri.Malloc( iSize, eTag, bZeroit, 4 ); + return ri.Z_Malloc( iSize, eTag, bZeroit, 4 ); } void R_Free( void *ptr ) { @@ -95,5 +95,5 @@ void R_MorphMallocTag( void *pvBuffer, memtag_t eDesiredTag ) { } void *R_Hunk_Alloc( int iSize, qboolean bZeroit ) { - return ri.Malloc( iSize, TAG_HUNKALLOC, bZeroit, 4 ); + return ri.Z_Malloc( iSize, TAG_HUNKALLOC, bZeroit, 4 ); } diff --git a/code/rd-vanilla/tr_surface.cpp b/code/rd-vanilla/tr_surface.cpp index 1e51e71c90..207a99986e 100644 --- a/code/rd-vanilla/tr_surface.cpp +++ b/code/rd-vanilla/tr_surface.cpp @@ -366,6 +366,62 @@ static void DoLine2( const vec3_t start, const vec3_t end, const vec3_t up, floa tess.indexes[tess.numIndexes++] = vbase + 3; } +static void DoLine_Oriented(const vec3_t start, const vec3_t end, const vec3_t up, float spanWidth) +{ + float spanWidth2; + int vbase; + + vbase = tess.numVertexes; + + spanWidth2 = -spanWidth; + + // FIXME: use quad stamp? + VectorMA(start, spanWidth, up, tess.xyz[tess.numVertexes]); + tess.texCoords[tess.numVertexes][0][0] = 0; + tess.texCoords[tess.numVertexes][0][1] = 0; + tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0];// * 0.25; + tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1];// * 0.25; + tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2];// * 0.25; + tess.vertexColors[tess.numVertexes][3] = backEnd.currentEntity->e.shaderRGBA[3];// * 0.25; + tess.numVertexes++; + + VectorMA(start, spanWidth2, up, tess.xyz[tess.numVertexes]); + tess.texCoords[tess.numVertexes][0][0] = 1; + tess.texCoords[tess.numVertexes][0][1] = 0; + tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0]; + tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1]; + tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2]; + tess.vertexColors[tess.numVertexes][3] = backEnd.currentEntity->e.shaderRGBA[3];// * 0.25; + tess.numVertexes++; + + VectorMA(end, spanWidth, up, tess.xyz[tess.numVertexes]); + + tess.texCoords[tess.numVertexes][0][0] = 0; + tess.texCoords[tess.numVertexes][0][1] = backEnd.currentEntity->e.data.line.stscale; + tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0]; + tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1]; + tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2]; + tess.vertexColors[tess.numVertexes][3] = backEnd.currentEntity->e.shaderRGBA[3];// * 0.25; + tess.numVertexes++; + + VectorMA(end, spanWidth2, up, tess.xyz[tess.numVertexes]); + tess.texCoords[tess.numVertexes][0][0] = 1; + tess.texCoords[tess.numVertexes][0][1] = backEnd.currentEntity->e.data.line.stscale; + tess.vertexColors[tess.numVertexes][0] = backEnd.currentEntity->e.shaderRGBA[0]; + tess.vertexColors[tess.numVertexes][1] = backEnd.currentEntity->e.shaderRGBA[1]; + tess.vertexColors[tess.numVertexes][2] = backEnd.currentEntity->e.shaderRGBA[2]; + tess.vertexColors[tess.numVertexes][3] = backEnd.currentEntity->e.shaderRGBA[3];// * 0.25; + tess.numVertexes++; + + tess.indexes[tess.numIndexes++] = vbase; + tess.indexes[tess.numIndexes++] = vbase + 1; + tess.indexes[tess.numIndexes++] = vbase + 2; + + tess.indexes[tess.numIndexes++] = vbase + 2; + tess.indexes[tess.numIndexes++] = vbase + 1; + tess.indexes[tess.numIndexes++] = vbase + 3; +} + //----------------- // RB_SurfaceLine //----------------- @@ -390,6 +446,23 @@ static void RB_SurfaceLine( void ) DoLine( start, end, right, e->radius); } +static void RB_SurfaceOrientedLine(void) +{ + refEntity_t *e; + vec3_t right; + vec3_t start, end; + + e = &backEnd.currentEntity->e; + + VectorCopy(e->oldorigin, end); + VectorCopy(e->origin, start); + + // compute side vector + VectorNormalize(e->axis[1]); + VectorCopy(e->axis[1], right); + DoLine_Oriented(start, end, right, e->data.line.width*0.5); +} + /* ============== RB_SurfaceCylinder @@ -1951,14 +2024,17 @@ void RB_SurfaceEntity( surfaceType_t *surfType ) { case RT_ORIENTED_QUAD: RB_SurfaceOrientedQuad(); break; - case RT_LINE: - RB_SurfaceLine(); + case RT_BEAM: + RB_SurfaceBeam(); break; case RT_ELECTRICITY: RB_SurfaceElectricity(); break; - case RT_BEAM: - RB_SurfaceBeam(); + case RT_LINE: + RB_SurfaceLine(); + break; + case RT_ORIENTEDLINE: + RB_SurfaceOrientedLine(); break; case RT_SABER_GLOW: RB_SurfaceSaberGlow(); @@ -1966,6 +2042,30 @@ void RB_SurfaceEntity( surfaceType_t *surfType ) { case RT_CYLINDER: RB_SurfaceCylinder(); break; + case RT_ENT_CHAIN: + { + static trRefEntity_t tempEnt = *backEnd.currentEntity; + + //rww - if not static then currentEntity is garbage because + //this is a local. This was not static in sof2.. but I guess + //they never check ce.renderfx so it didn't show up. + + const int start = backEnd.currentEntity->e.uRefEnt.uMini.miniStart; + const int count = backEnd.currentEntity->e.uRefEnt.uMini.miniCount; + assert(count > 0); + backEnd.currentEntity = &tempEnt; + + assert(backEnd.currentEntity->e.renderfx >= 0); + + for (int i = 0, j = start; i < count; i++, j++) + { + backEnd.currentEntity->e = backEnd.refdef.entities[j].e; + assert(backEnd.currentEntity->e.renderfx >= 0); + + RB_SurfaceEntity(surfType); + } + } + break; case RT_LATHE: RB_SurfaceLathe(); break; diff --git a/code/ui/ui_public.h b/code/ui/ui_public.h index e4f4ced11a..326afa0cd8 100644 --- a/code/ui/ui_public.h +++ b/code/ui/ui_public.h @@ -28,7 +28,7 @@ along with this program; if not, see . #include "../client/keycodes.h" -#define UI_API_VERSION 3 +#define UI_API_VERSION 4 typedef struct { @@ -84,7 +84,7 @@ typedef struct { // Nothing is drawn until R_RenderScene is called. void (*R_ClearScene)( void ); void (*R_AddRefEntityToScene)( const refEntity_t *re ); - void (*R_AddPolyToScene)( qhandle_t hShader , int numVerts, const polyVert_t *verts ); + void (*R_AddPolyToScene)( qhandle_t hShader , int numVerts, const polyVert_t *verts, int numPolys ); void (*R_AddLightToScene)( const vec3_t org, float intensity, float r, float g, float b ); void (*R_RenderScene)( const refdef_t *fd ); @@ -105,7 +105,7 @@ typedef struct { //========= model collision =============== // R_LerpTag is only valid for md3 models - void (*R_LerpTag)( orientation_t *tag, clipHandle_t mod, int startFrame, int endFrame, + int (*R_LerpTag)( orientation_t *tag, clipHandle_t mod, int startFrame, int endFrame, float frac, const char *tagName ); // =========== sound function calls =============== diff --git a/codemp/rd-common/tr_types.h b/codemp/rd-common/tr_types.h index 93c56777d3..d35e9030b3 100644 --- a/codemp/rd-common/tr_types.h +++ b/codemp/rd-common/tr_types.h @@ -75,6 +75,13 @@ along with this program; if not, see . #define RF_FORCEPOST 0x200000 //force it to post-render -rww +// SP renderfx flags, only use in SP! +#define RF_CAP_FRAMES 0x400000 // cap the model frames by the maxframes for one shot anims +#define RF_ALPHA_FADE 0x800000 // hacks blend mode and uses whatever the set alpha is. +#define RF_PULSATE 0x1000000 // for things like a dropped saber, where we want to add an extra visual clue +#define RF_G2MINLOD 0x2000000 // force Lowest lod on g2 +#define RF_MORELIGHT 0x4000000 // allways have some light (viewmodel, some items) | SP version which is different from MP + // refdef flags #define RDF_NOWORLDMODEL 1 // used for player configuration screen #define RDF_HYPERSPACE 4 // teleportation effect @@ -86,6 +93,10 @@ along with this program; if not, see . #define RDF_NOFOG 64 //no global fog in this scene (but still brush fog) -rww #define RDF_ForceSightOn 128 //using force sight +// SP refdef flags, only use in SP! +#define RDF_doLAGoggles 256 // SP only Light Amp goggles +#define RDF_doFullbright 512 // SP only Light Amp goggles + extern int skyboxportal; extern int drawskyboxportal; @@ -117,7 +128,12 @@ typedef enum { RT_CYLINDER, RT_ENT_CHAIN, - RT_MAX_REF_ENTITY_TYPE + RT_MAX_MP_REF_ENTITY_TYPE, + // SP ONLY Entity Types! + RT_LATHE, + RT_CLOUDS, + + RT_MAX_SP_REF_ENTITY_TYPE } refEntityType_t; typedef struct miniRefEntity_s @@ -279,20 +295,6 @@ Ghoul2 Insert Start #include "rd-common/mdx_format.h" #include "qcommon/qfiles.h" -// skins allow models to be retextured without modifying the model file -//this is a mock copy, renderers may have their own implementation. -// try not to break the ghoul2 code which is very implicit :/ -typedef struct _skinSurface_s { - char name[MAX_QPATH]; - void *shader; -} _skinSurface_t; - -typedef struct skin_s { - char name[MAX_QPATH]; // game path, including extension - int numSurfaces; - _skinSurface_t *surfaces[128]; -} skin_t; - /* Ghoul2 Insert End */ diff --git a/codemp/rd-dedicated/tr_local.h b/codemp/rd-dedicated/tr_local.h index 8915ac5b57..2da318024e 100644 --- a/codemp/rd-dedicated/tr_local.h +++ b/codemp/rd-dedicated/tr_local.h @@ -537,11 +537,18 @@ typedef struct trRefdef_s { //================================================================================= // skins allow models to be retextured without modifying the model file -typedef struct skinSurface_s { +typedef struct { char name[MAX_QPATH]; shader_t *shader; } skinSurface_t; +typedef struct skin_s { + char name[MAX_QPATH]; // game path, including extension + int numSurfaces; + skinSurface_t *surfaces[128]; +} skin_t; + + typedef struct fog_s { int originalBrushNumber; vec3_t bounds[2]; diff --git a/codemp/rd-dedicated/tr_skin.cpp b/codemp/rd-dedicated/tr_skin.cpp index ad179d0f35..a25589efed 100644 --- a/codemp/rd-dedicated/tr_skin.cpp +++ b/codemp/rd-dedicated/tr_skin.cpp @@ -146,7 +146,7 @@ qhandle_t RE_RegisterIndividualSkin( const char *name , qhandle_t hSkin) break; } surf = (skinSurface_t *) Hunk_Alloc( sizeof( *skin->surfaces[0] ), h_low ); - skin->surfaces[skin->numSurfaces] = (_skinSurface_t *)surf; + skin->surfaces[skin->numSurfaces] = (skinSurface_t *)surf; Q_strncpyz( surf->name, surfName, sizeof( surf->name ) ); @@ -378,7 +378,7 @@ void R_InitSkins( void ) { skin = tr.skins[0] = (struct skin_s *)ri.Hunk_Alloc( sizeof( skin_t ), h_low ); Q_strncpyz( skin->name, "", sizeof( skin->name ) ); skin->numSurfaces = 1; - skin->surfaces[0] = (_skinSurface_t *)ri.Hunk_Alloc( sizeof( skinSurface_t ), h_low ); + skin->surfaces[0] = (skinSurface_t *)ri.Hunk_Alloc( sizeof( skinSurface_t ), h_low ); skin->surfaces[0]->shader = tr.defaultShader; } diff --git a/codemp/rd-rend2/CMakeLists.txt b/codemp/rd-rend2/CMakeLists.txt index 786cf254fc..073c92b5b4 100644 --- a/codemp/rd-rend2/CMakeLists.txt +++ b/codemp/rd-rend2/CMakeLists.txt @@ -5,78 +5,79 @@ endif(NOT InOpenJK) set(MPRend2IncludeDirectories "${SharedDir}" + "${SharedDir}/rd-rend2" "${MPDir}" "${MPDir}/rd-rend2" "${GSLIncludeDirectory}" ) set(MPRend2Files - "${MPDir}/rd-rend2/iqm.h" - "${MPDir}/rd-rend2/glext.h" - "${MPDir}/rd-rend2/qgl.h" - "${MPDir}/rd-rend2/stb_image.h" + "${SharedDir}/rd-rend2/iqm.h" + "${SharedDir}/rd-rend2/glext.h" + "${SharedDir}/rd-rend2/qgl.h" + "${SharedDir}/rd-rend2/stb_image.h" "${MPDir}/rd-rend2/G2_API.cpp" "${MPDir}/rd-rend2/G2_bolts.cpp" "${MPDir}/rd-rend2/G2_bones.cpp" - "${MPDir}/rd-rend2/G2_gore_r2.cpp" - "${MPDir}/rd-rend2/G2_gore_r2.h" + "${SharedDir}/rd-rend2/G2_gore_r2.cpp" + "${SharedDir}/rd-rend2/G2_gore_r2.h" "${MPDir}/rd-rend2/G2_misc.cpp" "${MPDir}/rd-rend2/G2_surfaces.cpp" - "${MPDir}/rd-rend2/tr_allocator.cpp" - "${MPDir}/rd-rend2/tr_allocator.h" - "${MPDir}/rd-rend2/tr_animation.cpp" - "${MPDir}/rd-rend2/tr_backend.cpp" - "${MPDir}/rd-rend2/tr_bsp.cpp" - "${MPDir}/rd-rend2/tr_cache.cpp" - "${MPDir}/rd-rend2/tr_cache.h" - "${MPDir}/rd-rend2/tr_cmds.cpp" - "${MPDir}/rd-rend2/tr_curve.cpp" - "${MPDir}/rd-rend2/tr_decals.cpp" - "${MPDir}/rd-rend2/tr_extensions.cpp" - "${MPDir}/rd-rend2/tr_extramath.cpp" - "${MPDir}/rd-rend2/tr_extramath.h" - "${MPDir}/rd-rend2/tr_extratypes.h" - "${MPDir}/rd-rend2/tr_fbo.cpp" - "${MPDir}/rd-rend2/tr_fbo.h" - "${MPDir}/rd-rend2/tr_flares.cpp" - "${MPDir}/rd-rend2/tr_ghoul2.cpp" - "${MPDir}/rd-rend2/tr_glsl.cpp" - "${MPDir}/rd-rend2/tr_glsl_parse.cpp" - "${MPDir}/rd-rend2/tr_image.cpp" - "${MPDir}/rd-rend2/tr_image_stb.cpp" + "${SharedDir}/rd-rend2/tr_allocator.cpp" + "${SharedDir}/rd-rend2/tr_allocator.h" + "${SharedDir}/rd-rend2/tr_animation.cpp" + "${SharedDir}/rd-rend2/tr_backend.cpp" + "${SharedDir}/rd-rend2/tr_bsp.cpp" + "${SharedDir}/rd-rend2/tr_cache.cpp" + "${SharedDir}/rd-rend2/tr_cache.h" + "${SharedDir}/rd-rend2/tr_cmds.cpp" + "${SharedDir}/rd-rend2/tr_curve.cpp" + "${SharedDir}/rd-rend2/tr_decals.cpp" + "${SharedDir}/rd-rend2/tr_extensions.cpp" + "${SharedDir}/rd-rend2/tr_extramath.cpp" + "${SharedDir}/rd-rend2/tr_extramath.h" + "${SharedDir}/rd-rend2/tr_extratypes.h" + "${SharedDir}/rd-rend2/tr_fbo.cpp" + "${SharedDir}/rd-rend2/tr_fbo.h" + "${SharedDir}/rd-rend2/tr_flares.cpp" + "${SharedDir}/rd-rend2/tr_ghoul2.cpp" + "${SharedDir}/rd-rend2/tr_glsl.cpp" + "${SharedDir}/rd-rend2/tr_glsl_parse.cpp" + "${SharedDir}/rd-rend2/tr_image.cpp" + "${SharedDir}/rd-rend2/tr_image_stb.cpp" "${MPDir}/rd-rend2/tr_init.cpp" - "${MPDir}/rd-rend2/tr_light.cpp" - "${MPDir}/rd-rend2/tr_local.h" - "${MPDir}/rd-rend2/tr_main.cpp" - "${MPDir}/rd-rend2/tr_marks.cpp" - "${MPDir}/rd-rend2/tr_mesh.cpp" - "${MPDir}/rd-rend2/tr_model.cpp" - "${MPDir}/rd-rend2/tr_model_iqm.cpp" - "${MPDir}/rd-rend2/tr_postprocess.cpp" - "${MPDir}/rd-rend2/tr_postprocess.h" - "${MPDir}/rd-rend2/tr_scene.cpp" - "${MPDir}/rd-rend2/tr_shade.cpp" - "${MPDir}/rd-rend2/tr_shade_calc.cpp" - "${MPDir}/rd-rend2/tr_shader.cpp" - "${MPDir}/rd-rend2/tr_shadows.cpp" - "${MPDir}/rd-rend2/tr_skin.cpp" - "${MPDir}/rd-rend2/tr_sky.cpp" - "${MPDir}/rd-rend2/tr_subs.cpp" - "${MPDir}/rd-rend2/tr_surface.cpp" - "${MPDir}/rd-rend2/tr_tangentspace.cpp" - "${MPDir}/rd-rend2/tr_vbo.cpp" - "${MPDir}/rd-rend2/tr_world.cpp" - "${MPDir}/rd-rend2/tr_weather.cpp" - "${MPDir}/rd-rend2/tr_weather.h") + "${SharedDir}/rd-rend2/tr_light.cpp" + "${SharedDir}/rd-rend2/tr_local.h" + "${SharedDir}/rd-rend2/tr_main.cpp" + "${SharedDir}/rd-rend2/tr_marks.cpp" + "${SharedDir}/rd-rend2/tr_mesh.cpp" + "${SharedDir}/rd-rend2/tr_model.cpp" + "${SharedDir}/rd-rend2/tr_model_iqm.cpp" + "${SharedDir}/rd-rend2/tr_postprocess.cpp" + "${SharedDir}/rd-rend2/tr_postprocess.h" + "${SharedDir}/rd-rend2/tr_scene.cpp" + "${SharedDir}/rd-rend2/tr_shade.cpp" + "${SharedDir}/rd-rend2/tr_shade_calc.cpp" + "${SharedDir}/rd-rend2/tr_shader.cpp" + "${SharedDir}/rd-rend2/tr_shadows.cpp" + "${SharedDir}/rd-rend2/tr_skin.cpp" + "${SharedDir}/rd-rend2/tr_sky.cpp" + "${SharedDir}/rd-rend2/tr_subs.cpp" + "${SharedDir}/rd-rend2/tr_surface.cpp" + "${SharedDir}/rd-rend2/tr_tangentspace.cpp" + "${SharedDir}/rd-rend2/tr_vbo.cpp" + "${SharedDir}/rd-rend2/tr_world.cpp" + "${SharedDir}/rd-rend2/tr_weather.cpp" + "${SharedDir}/rd-rend2/tr_weather.h") source_group("renderer" FILES ${MPRend2Files}) -file(GLOB MPRend2GLSLFiles "${MPDir}/rd-rend2/glsl/*.glsl") +file(GLOB MPRend2GLSLFiles "${SharedDir}/rd-rend2/glsl/*.glsl") source_group("renderer\\glsl" FILES ${MPRend2GLSLFiles}) set(MPRend2Files ${MPRend2Files} ${MPRend2GLSLFiles}) set(MPRend2MikktFiles - "${MPDir}/rd-rend2/MikkTSpace/mikktspace.h" - "${MPDir}/rd-rend2/MikkTSpace/mikktspace.c") + "${SharedDir}/rd-rend2/MikkTSpace/mikktspace.h" + "${SharedDir}/rd-rend2/MikkTSpace/mikktspace.c") source_group("MikktSpace" FILES ${MPRend2MikktFiles}) set(MPRend2Files ${MPRend2Files} ${MPRend2MikktFiles}) @@ -184,10 +185,10 @@ target_include_directories(${MPRend2} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) # GLSL shader file generator add_executable(compact_glsl - ${MPDir}/rd-rend2/glsl/compact.cpp - ${MPDir}/rd-rend2/tr_allocator.cpp - ${MPDir}/rd-rend2/tr_allocator.h - ${MPDir}/rd-rend2/tr_glsl_parse.cpp) + ${SharedDir}/rd-rend2/glsl/compact.cpp + ${SharedDir}/rd-rend2/tr_allocator.cpp + ${SharedDir}/rd-rend2/tr_allocator.h + ${SharedDir}/rd-rend2/tr_glsl_parse.cpp) target_compile_definitions(compact_glsl PRIVATE "GLSL_BUILDTOOL" "NOMINMAX") if (NOT WIN32 AND NOT APPLE) target_compile_definitions(compact_glsl PRIVATE "ARCH_STRING=\"${Architecture}\"") diff --git a/codemp/rd-rend2/G2_API.cpp b/codemp/rd-rend2/G2_API.cpp index f93a2ad8fb..9924b1126c 100644 --- a/codemp/rd-rend2/G2_API.cpp +++ b/codemp/rd-rend2/G2_API.cpp @@ -2988,7 +2988,8 @@ qboolean G2_TestModelPointers(CGhoul2Info *ghlInfo) // returns true if the model ghlInfo->mModel = RE_RegisterModel(ghlInfo->mFileName); } ghlInfo->currentModel = R_GetModelByHandle(ghlInfo->mModel); - if (ghlInfo->currentModel) + if (ghlInfo->currentModel && + ghlInfo->currentModel->type == MOD_MDXM) //Rend2 - data is a union now, so we need to make sure it's also a glm that is loaded { if (ghlInfo->currentModel->data.glm && ghlInfo->currentModel->data.glm->header) diff --git a/codemp/rd-rend2/tr_init.cpp b/codemp/rd-rend2/tr_init.cpp index 183fbcae90..cff5c7dc17 100644 --- a/codemp/rd-rend2/tr_init.cpp +++ b/codemp/rd-rend2/tr_init.cpp @@ -34,6 +34,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA static size_t STATIC_UNIFORM_BUFFER_SIZE = 1 * 1024 * 1024; static size_t FRAME_UNIFORM_BUFFER_SIZE = 8*1024*1024; +static size_t FRAME_SCENE_UNIFORM_BUFFER_SIZE = 1 * 1024 * 1024; static size_t FRAME_VERTEX_BUFFER_SIZE = 12*1024*1024; static size_t FRAME_INDEX_BUFFER_SIZE = 4*1024*1024; @@ -280,7 +281,7 @@ static void R_Splash() { const GLfloat black[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - qglViewport( 0, 0, glConfig.vidWidth, glConfig.vidHeight ); + GL_SetViewportAndScissor( 0, 0, glConfig.vidWidth, glConfig.vidHeight ); qglClearBufferfv(GL_COLOR, 0, black); qglClear(GL_DEPTH_BUFFER_BIT); @@ -1204,6 +1205,7 @@ void GL_SetDefaultState( void ) qglEnable(GL_PROGRAM_POINT_SIZE); qglDisable( GL_CULL_FACE ); qglDisable( GL_BLEND ); + glState.blend = false; qglEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); @@ -1477,13 +1479,13 @@ void R_Register( void ) r_toneMap = ri.Cvar_Get( "r_toneMap", "1", CVAR_ARCHIVE | CVAR_LATCH, "Disable/enable tonemapping" ); r_forceToneMap = ri.Cvar_Get( "r_forceToneMap", "0", CVAR_CHEAT, "" ); r_forceToneMapMin = ri.Cvar_Get( "r_forceToneMapMin", "-8.0", CVAR_CHEAT, "" ); - r_forceToneMapAvg = ri.Cvar_Get( "r_forceToneMapAvg", "-2.0", CVAR_CHEAT, "" ); + r_forceToneMapAvg = ri.Cvar_Get( "r_forceToneMapAvg", "-1.0", CVAR_CHEAT, "" ); r_forceToneMapMax = ri.Cvar_Get( "r_forceToneMapMax", "0.0", CVAR_CHEAT, "" ); r_autoExposure = ri.Cvar_Get( "r_autoExposure", "1", CVAR_ARCHIVE, "Disable/enable auto exposure" ); r_forceAutoExposure = ri.Cvar_Get( "r_forceAutoExposure", "0", CVAR_CHEAT, "" ); - r_forceAutoExposureMin = ri.Cvar_Get( "r_forceAutoExposureMin", "-2.0", CVAR_CHEAT, "" ); - r_forceAutoExposureMax = ri.Cvar_Get( "r_forceAutoExposureMax", "2.0", CVAR_CHEAT, "" ); + r_forceAutoExposureMin = ri.Cvar_Get( "r_forceAutoExposureMin", "-3.0", CVAR_CHEAT, "" ); + r_forceAutoExposureMax = ri.Cvar_Get( "r_forceAutoExposureMax", "1.0", CVAR_CHEAT, "" ); r_cameraExposure = ri.Cvar_Get( "r_cameraExposure", "0", CVAR_CHEAT, "" ); @@ -1672,23 +1674,27 @@ static void R_InitBackEndFrameData() GLuint timerQueries[MAX_GPU_TIMERS*MAX_FRAMES]; qglGenQueries(MAX_GPU_TIMERS*MAX_FRAMES, timerQueries); - GLuint ubos[MAX_FRAMES]; - qglGenBuffers(MAX_FRAMES, ubos); + GLuint ubos[MAX_FRAMES * MAX_SCENES]; + qglGenBuffers(MAX_FRAMES * MAX_SCENES, ubos); for ( int i = 0; i < MAX_FRAMES; i++ ) { gpuFrame_t *frame = backEndData->frames + i; const GLbitfield mapBits = GL_MAP_WRITE_BIT | GL_MAP_COHERENT_BIT | GL_MAP_PERSISTENT_BIT; - frame->ubo = ubos[i]; - frame->uboWriteOffset = 0; - frame->uboSize = FRAME_UNIFORM_BUFFER_SIZE; - qglBindBuffer(GL_UNIFORM_BUFFER, frame->ubo); - glState.currentGlobalUBO = frame->ubo; - - // TODO: persistently mapped UBOs - qglBufferData(GL_UNIFORM_BUFFER, FRAME_UNIFORM_BUFFER_SIZE, + for (byte j = 0; j < MAX_SCENES; j++) + { + size_t BUFFER_SIZE = j == 0 ? FRAME_UNIFORM_BUFFER_SIZE : FRAME_SCENE_UNIFORM_BUFFER_SIZE; + frame->ubo[j] = ubos[i * MAX_SCENES + j]; + frame->uboWriteOffset[j] = 0; + frame->uboSize[j] = BUFFER_SIZE; + qglBindBuffer(GL_UNIFORM_BUFFER, frame->ubo[j]); + glState.currentGlobalUBO = frame->ubo[j]; + + // TODO: persistently mapped UBOs + qglBufferData(GL_UNIFORM_BUFFER, BUFFER_SIZE, nullptr, GL_DYNAMIC_DRAW); + } frame->dynamicVbo = R_CreateVBO(nullptr, FRAME_VERTEX_BUFFER_SIZE, VBO_USAGE_DYNAMIC); @@ -1731,7 +1737,7 @@ static void R_InitGoreVao() { tr.goreVBO = R_CreateVBO( nullptr, - sizeof(g2GoreVert_t) * MAX_LODS * MAX_GORE_RECORDS * MAX_GORE_VERTS * MAX_FRAMES, + sizeof(g2GoreVert_t) * MAX_GORE_RECORDS * MAX_GORE_VERTS * MAX_FRAMES, VBO_USAGE_DYNAMIC); tr.goreVBO->offsets[ATTR_INDEX_POSITION] = offsetof(g2GoreVert_t, position); tr.goreVBO->offsets[ATTR_INDEX_NORMAL] = offsetof(g2GoreVert_t, normal); @@ -1756,11 +1762,13 @@ static void R_InitGoreVao() tr.goreIBO = R_CreateIBO( nullptr, - sizeof(glIndex_t) * MAX_LODS * MAX_GORE_RECORDS * MAX_GORE_INDECIES * MAX_FRAMES, + sizeof(glIndex_t) * MAX_GORE_RECORDS * MAX_GORE_INDECIES * MAX_FRAMES, VBO_USAGE_DYNAMIC); tr.goreIBOCurrentIndex = 0; tr.goreVBOCurrentIndex = 0; + + GL_CheckErrors(); } #endif @@ -1883,7 +1891,7 @@ static void R_ShutdownBackEndFrameData() frame->sync = NULL; } - qglDeleteBuffers(1, &frame->ubo); + qglDeleteBuffers(MAX_SCENES, frame->ubo); if ( glRefConfig.immutableBuffers ) { @@ -1901,6 +1909,7 @@ static void R_ShutdownBackEndFrameData() } } +static bool r_inited = false; /* =============== R_Init @@ -1910,6 +1919,9 @@ void R_Init( void ) { byte *ptr; int i; + if (r_inited) + return; + ri.Printf( PRINT_ALL, "----- R_Init -----\n" ); // clear all our internal state @@ -2022,6 +2034,7 @@ void R_Init( void ) { // print info GfxInfo_f(); + r_inited = true; ri.Printf( PRINT_ALL, "----- finished R_Init -----\n" ); } @@ -2047,21 +2060,23 @@ void RE_Shutdown( qboolean destroyWindow, qboolean restarting ) { R_ShutdownWeatherSystem(); R_ShutdownFonts(); - if ( tr.registered ) { + + if (r_inited) + { R_ShutDownQueries(); FBO_Shutdown(); R_DeleteTextures(); R_DestroyGPUBuffers(); GLSL_ShutdownGPUShaders(); + } - if ( destroyWindow && restarting ) - { - ri.Z_Free((void *)glConfig.extensions_string); - ri.Z_Free((void *)glConfigExt.originalExtensionString); + if (destroyWindow && restarting && tr.registered) + { + ri.Z_Free((void *)glConfig.extensions_string); + ri.Z_Free((void *)glConfigExt.originalExtensionString); - qglDeleteVertexArrays(1, &tr.globalVao); - SaveGhoul2InfoArray(); - } + qglDeleteVertexArrays(1, &tr.globalVao); + SaveGhoul2InfoArray(); } // shut down platform specific OpenGL stuff @@ -2070,6 +2085,7 @@ void RE_Shutdown( qboolean destroyWindow, qboolean restarting ) { } tr.registered = qfalse; + r_inited = false; backEndData = NULL; } diff --git a/codemp/rd-vanilla/tr_local.h b/codemp/rd-vanilla/tr_local.h index dcef60d901..f13337bbf8 100644 --- a/codemp/rd-vanilla/tr_local.h +++ b/codemp/rd-vanilla/tr_local.h @@ -554,7 +554,6 @@ typedef struct trRefdef_s { int num_entities; trRefEntity_t *entities; - trMiniRefEntity_t *miniEntities; int num_dlights; struct dlight_s *dlights; @@ -570,11 +569,18 @@ typedef struct trRefdef_s { //================================================================================= // skins allow models to be retextured without modifying the model file -typedef struct skinSurface_s { +typedef struct { char name[MAX_QPATH]; shader_t *shader; } skinSurface_t; +typedef struct skin_s { + char name[MAX_QPATH]; // game path, including extension + int numSurfaces; + skinSurface_t *surfaces[128]; +} skin_t; + + typedef struct fog_s { int originalBrushNumber; vec3_t bounds[2]; @@ -1096,6 +1102,7 @@ struct glconfigExt_t { glconfig_t *glConfig; + qboolean textureFilterAnisotropicAvailable; qboolean doGammaCorrectionWithShaders; qboolean doStencilShadowsInOneDrawcall; const char *originalExtensionString; diff --git a/codemp/rd-vanilla/tr_scene.cpp b/codemp/rd-vanilla/tr_scene.cpp index 9c0025485a..473d01e182 100644 --- a/codemp/rd-vanilla/tr_scene.cpp +++ b/codemp/rd-vanilla/tr_scene.cpp @@ -36,8 +36,6 @@ static int r_firstSceneDlight; static int r_numentities; static int r_firstSceneEntity; static int r_numminientities; -static int r_firstSceneMiniEntity; -static int refEntParent = -1; static int r_numpolys; static int r_firstScenePoly; @@ -63,9 +61,7 @@ void R_InitNextFrame( void ) { r_numentities = 0; r_firstSceneEntity = 0; - refEntParent = -1; r_numminientities = 0; - r_firstSceneMiniEntity = 0; r_numpolys = 0; r_firstScenePoly = 0; @@ -84,8 +80,6 @@ void RE_ClearScene( void ) { r_firstSceneDlight = r_numdlights; r_firstSceneEntity = r_numentities; r_firstScenePoly = r_numpolys; - refEntParent = -1; - r_firstSceneMiniEntity = r_numminientities; } /* @@ -238,8 +232,8 @@ void RE_AddRefEntityToScene( const refEntity_t *ent ) { assert(ent->hModel || ent->ghoul2 || ent->customShader); } #endif - - if ( (int)ent->reType < 0 || ent->reType >= RT_MAX_REF_ENTITY_TYPE ) { + // TODO: We could implement RT_LATHE and RT_CLOUDS here in MP too to check the same as in the SP renderer -> less differences + if ( (int)ent->reType < 0 || ent->reType >= RT_MAX_MP_REF_ENTITY_TYPE ) { Com_Error( ERR_DROP, "RE_AddRefEntityToScene: bad reType %i", ent->reType ); } @@ -256,19 +250,6 @@ void RE_AddRefEntityToScene( const refEntity_t *ent ) { } } - /* - if (ent->reType == RT_ENT_CHAIN) - { - refEntParent = r_numentities; - backEndData->entities[r_numentities].e.uRefEnt.uMini.miniStart = r_numminientities - r_firstSceneMiniEntity; - backEndData->entities[r_numentities].e.uRefEnt.uMini.miniCount = 0; - } - else - { - */ - refEntParent = -1; - //} - r_numentities++; } @@ -288,50 +269,20 @@ void RE_AddRefEntityToScene( const refEntity_t *ent ) { ************************************************************************************************/ void RE_AddMiniRefEntityToScene( const miniRefEntity_t *ent ) { -#if 0 - refEntity_t *parent; -#endif - if ( !tr.registered ) { return; } if (!ent) { - refEntParent = -1; return; } -#if 1 //i hate you minirefent! refEntity_t tempEnt; memcpy(&tempEnt, ent, sizeof(*ent)); memset(((char *)&tempEnt)+sizeof(*ent), 0, sizeof(tempEnt) - sizeof(*ent)); RE_AddRefEntityToScene(&tempEnt); -#else - - if ( ent->reType < 0 || ent->reType >= RT_MAX_REF_ENTITY_TYPE ) - { - Com_Error( ERR_DROP, "RE_AddMiniRefEntityToScene: bad reType %i", ent->reType ); - } - - if (!r_numentities || refEntParent == -1 || r_numminientities >= MAX_MINI_ENTITIES) - { //rww - add it as a refent also if we run out of minis -// Com_Error( ERR_DROP, "RE_AddMiniRefEntityToScene: mini without parent ref ent"); - refEntity_t tempEnt; - - memcpy(&tempEnt, ent, sizeof(*ent)); - memset(((char *)&tempEnt)+sizeof(*ent), 0, sizeof(tempEnt) - sizeof(*ent)); - RE_AddRefEntityToScene(&tempEnt); - return; - } - - parent = &backEndData->entities[refEntParent].e; - parent->uRefEnt.uMini.miniCount++; - - backEndData->miniEntities[r_numminientities].e = *ent; - r_numminientities++; -#endif } /* @@ -491,7 +442,6 @@ void RE_RenderScene( const refdef_t *fd ) { tr.refdef.num_entities = r_numentities - r_firstSceneEntity; tr.refdef.entities = &backEndData->entities[r_firstSceneEntity]; - tr.refdef.miniEntities = &backEndData->miniEntities[r_firstSceneMiniEntity]; tr.refdef.num_dlights = r_numdlights - r_firstSceneDlight; tr.refdef.dlights = &backEndData->dlights[r_firstSceneDlight]; @@ -549,12 +499,9 @@ void RE_RenderScene( const refdef_t *fd ) { // the next scene rendered in this frame will tack on after this one r_firstSceneDrawSurf = tr.refdef.numDrawSurfs; r_firstSceneEntity = r_numentities; - r_firstSceneMiniEntity = r_numminientities; r_firstSceneDlight = r_numdlights; r_firstScenePoly = r_numpolys; - refEntParent = -1; - tr.frontEndMsec += ri.Milliseconds()*ri.Cvar_VariableValue( "timescale" ) - startTime; RE_RenderWorldEffects(); diff --git a/codemp/rd-vanilla/tr_skin.cpp b/codemp/rd-vanilla/tr_skin.cpp index 57ff06618c..ce43a02d33 100644 --- a/codemp/rd-vanilla/tr_skin.cpp +++ b/codemp/rd-vanilla/tr_skin.cpp @@ -160,7 +160,7 @@ qhandle_t RE_RegisterIndividualSkin( const char *name , qhandle_t hSkin) break; } surf = (skinSurface_t *) Hunk_Alloc( sizeof( *skin->surfaces[0] ), h_low ); - skin->surfaces[skin->numSurfaces] = (_skinSurface_t *)surf; + skin->surfaces[skin->numSurfaces] = (skinSurface_t *)surf; Q_strncpyz( surf->name, surfName, sizeof( surf->name ) ); @@ -393,7 +393,7 @@ void R_InitSkins( void ) { skin = tr.skins[0] = (struct skin_s *)ri.Hunk_Alloc( sizeof( skin_t ), h_low ); Q_strncpyz( skin->name, "", sizeof( skin->name ) ); skin->numSurfaces = 1; - skin->surfaces[0] = (_skinSurface_t *)ri.Hunk_Alloc( sizeof( skinSurface_t ), h_low ); + skin->surfaces[0] = (skinSurface_t *)ri.Hunk_Alloc( sizeof( skinSurface_t ), h_low ); skin->surfaces[0]->shader = tr.defaultShader; } diff --git a/codemp/rd-vanilla/tr_surface.cpp b/codemp/rd-vanilla/tr_surface.cpp index 3be021dce6..ab8bf97303 100644 --- a/codemp/rd-vanilla/tr_surface.cpp +++ b/codemp/rd-vanilla/tr_surface.cpp @@ -1622,22 +1622,22 @@ void RB_SurfaceEntity( surfaceType_t *surfType ) { break; case RT_ENT_CHAIN: { - int i, count, start; - static trRefEntity_t tempEnt = *backEnd.currentEntity; + static trRefEntity_t tempEnt = *backEnd.currentEntity; + //rww - if not static then currentEntity is garbage because //this is a local. This was not static in sof2.. but I guess //they never check ce.renderfx so it didn't show up. - start = backEnd.currentEntity->e.uRefEnt.uMini.miniStart; - count = backEnd.currentEntity->e.uRefEnt.uMini.miniCount; + const int start = backEnd.currentEntity->e.uRefEnt.uMini.miniStart; + const int count = backEnd.currentEntity->e.uRefEnt.uMini.miniCount; assert(count > 0); backEnd.currentEntity = &tempEnt; assert(backEnd.currentEntity->e.renderfx >= 0); - for(i=0;ie, &backEnd.refdef.miniEntities[start+i], sizeof(backEnd.refdef.miniEntities[start+i])); + backEnd.currentEntity->e = backEnd.refdef.entities[j].e; assert(backEnd.currentEntity->e.renderfx >= 0); diff --git a/shared/KHR/khrplatform.h b/shared/KHR/khrplatform.h new file mode 100644 index 0000000000..01646449ca --- /dev/null +++ b/shared/KHR/khrplatform.h @@ -0,0 +1,311 @@ +#ifndef __khrplatform_h_ +#define __khrplatform_h_ + +/* +** Copyright (c) 2008-2018 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +/* Khronos platform-specific types and definitions. + * + * The master copy of khrplatform.h is maintained in the Khronos EGL + * Registry repository at https://github.com/KhronosGroup/EGL-Registry + * The last semantic modification to khrplatform.h was at commit ID: + * 67a3e0864c2d75ea5287b9f3d2eb74a745936692 + * + * Adopters may modify this file to suit their platform. Adopters are + * encouraged to submit platform specific modifications to the Khronos + * group so that they can be included in future versions of this file. + * Please submit changes by filing pull requests or issues on + * the EGL Registry repository linked above. + * + * + * See the Implementer's Guidelines for information about where this file + * should be located on your system and for more details of its use: + * http://www.khronos.org/registry/implementers_guide.pdf + * + * This file should be included as + * #include + * by Khronos client API header files that use its types and defines. + * + * The types in khrplatform.h should only be used to define API-specific types. + * + * Types defined in khrplatform.h: + * khronos_int8_t signed 8 bit + * khronos_uint8_t unsigned 8 bit + * khronos_int16_t signed 16 bit + * khronos_uint16_t unsigned 16 bit + * khronos_int32_t signed 32 bit + * khronos_uint32_t unsigned 32 bit + * khronos_int64_t signed 64 bit + * khronos_uint64_t unsigned 64 bit + * khronos_intptr_t signed same number of bits as a pointer + * khronos_uintptr_t unsigned same number of bits as a pointer + * khronos_ssize_t signed size + * khronos_usize_t unsigned size + * khronos_float_t signed 32 bit floating point + * khronos_time_ns_t unsigned 64 bit time in nanoseconds + * khronos_utime_nanoseconds_t unsigned time interval or absolute time in + * nanoseconds + * khronos_stime_nanoseconds_t signed time interval in nanoseconds + * khronos_boolean_enum_t enumerated boolean type. This should + * only be used as a base type when a client API's boolean type is + * an enum. Client APIs which use an integer or other type for + * booleans cannot use this as the base type for their boolean. + * + * Tokens defined in khrplatform.h: + * + * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. + * + * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. + * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. + * + * Calling convention macros defined in this file: + * KHRONOS_APICALL + * KHRONOS_APIENTRY + * KHRONOS_APIATTRIBUTES + * + * These may be used in function prototypes as: + * + * KHRONOS_APICALL void KHRONOS_APIENTRY funcname( + * int arg1, + * int arg2) KHRONOS_APIATTRIBUTES; + */ + +#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC) +# define KHRONOS_STATIC 1 +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APICALL + *------------------------------------------------------------------------- + * This precedes the return type of the function in the function prototype. + */ +#if defined(KHRONOS_STATIC) + /* If the preprocessor constant KHRONOS_STATIC is defined, make the + * header compatible with static linking. */ +# define KHRONOS_APICALL +#elif defined(_WIN32) +# define KHRONOS_APICALL __declspec(dllimport) +#elif defined (__SYMBIAN32__) +# define KHRONOS_APICALL IMPORT_C +#elif defined(__ANDROID__) +# define KHRONOS_APICALL __attribute__((visibility("default"))) +#else +# define KHRONOS_APICALL +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIENTRY + *------------------------------------------------------------------------- + * This follows the return type of the function and precedes the function + * name in the function prototype. + */ +#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) + /* Win32 but not WinCE */ +# define KHRONOS_APIENTRY __stdcall +#else +# define KHRONOS_APIENTRY +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIATTRIBUTES + *------------------------------------------------------------------------- + * This follows the closing parenthesis of the function prototype arguments. + */ +#if defined (__ARMCC_2__) +#define KHRONOS_APIATTRIBUTES __softfp +#else +#define KHRONOS_APIATTRIBUTES +#endif + +/*------------------------------------------------------------------------- + * basic type definitions + *-----------------------------------------------------------------------*/ +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) + + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 +/* + * To support platform where unsigned long cannot be used interchangeably with + * inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t. + * Ideally, we could just use (u)intptr_t everywhere, but this could result in + * ABI breakage if khronos_uintptr_t is changed from unsigned long to + * unsigned long long or similar (this results in different C++ name mangling). + * To avoid changes for existing platforms, we restrict usage of intptr_t to + * platforms where the size of a pointer is larger than the size of long. + */ +#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__) +#if __SIZEOF_POINTER__ > __SIZEOF_LONG__ +#define KHRONOS_USE_INTPTR_T +#endif +#endif + +#elif defined(__VMS ) || defined(__sgi) + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(_WIN32) && !defined(__SCITECH_SNAP__) + +/* + * Win32 + */ +typedef __int32 khronos_int32_t; +typedef unsigned __int32 khronos_uint32_t; +typedef __int64 khronos_int64_t; +typedef unsigned __int64 khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(__sun__) || defined(__digital__) + +/* + * Sun or Digital + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#if defined(__arch64__) || defined(_LP64) +typedef long int khronos_int64_t; +typedef unsigned long int khronos_uint64_t; +#else +typedef long long int khronos_int64_t; +typedef unsigned long long int khronos_uint64_t; +#endif /* __arch64__ */ +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif 0 + +/* + * Hypothetical platform with no float or int64 support + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#define KHRONOS_SUPPORT_INT64 0 +#define KHRONOS_SUPPORT_FLOAT 0 + +#else + +/* + * Generic fallback + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#endif + + +/* + * Types that are (so far) the same on all platforms + */ +typedef signed char khronos_int8_t; +typedef unsigned char khronos_uint8_t; +typedef signed short int khronos_int16_t; +typedef unsigned short int khronos_uint16_t; + +/* + * Types that differ between LLP64 and LP64 architectures - in LLP64, + * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears + * to be the only LLP64 architecture in current use. + */ +#ifdef KHRONOS_USE_INTPTR_T +typedef intptr_t khronos_intptr_t; +typedef uintptr_t khronos_uintptr_t; +#elif defined(_WIN64) +typedef signed long long int khronos_intptr_t; +typedef unsigned long long int khronos_uintptr_t; +#else +typedef signed long int khronos_intptr_t; +typedef unsigned long int khronos_uintptr_t; +#endif + +#if defined(_WIN64) +typedef signed long long int khronos_ssize_t; +typedef unsigned long long int khronos_usize_t; +#else +typedef signed long int khronos_ssize_t; +typedef unsigned long int khronos_usize_t; +#endif + +#if KHRONOS_SUPPORT_FLOAT +/* + * Float type + */ +typedef float khronos_float_t; +#endif + +#if KHRONOS_SUPPORT_INT64 +/* Time types + * + * These types can be used to represent a time interval in nanoseconds or + * an absolute Unadjusted System Time. Unadjusted System Time is the number + * of nanoseconds since some arbitrary system event (e.g. since the last + * time the system booted). The Unadjusted System Time is an unsigned + * 64 bit value that wraps back to 0 every 584 years. Time intervals + * may be either signed or unsigned. + */ +typedef khronos_uint64_t khronos_utime_nanoseconds_t; +typedef khronos_int64_t khronos_stime_nanoseconds_t; +#endif + +/* + * Dummy value used to pad enum types to 32 bits. + */ +#ifndef KHRONOS_MAX_ENUM +#define KHRONOS_MAX_ENUM 0x7FFFFFFF +#endif + +/* + * Enumerated boolean type + * + * Values other than zero should be considered to be true. Therefore + * comparisons should not be made against KHRONOS_TRUE. + */ +typedef enum { + KHRONOS_FALSE = 0, + KHRONOS_TRUE = 1, + KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM +} khronos_boolean_enum_t; + +#endif /* __khrplatform_h_ */ diff --git a/codemp/rd-rend2/G2_gore_r2.cpp b/shared/rd-rend2/G2_gore_r2.cpp similarity index 100% rename from codemp/rd-rend2/G2_gore_r2.cpp rename to shared/rd-rend2/G2_gore_r2.cpp diff --git a/codemp/rd-rend2/G2_gore_r2.h b/shared/rd-rend2/G2_gore_r2.h similarity index 100% rename from codemp/rd-rend2/G2_gore_r2.h rename to shared/rd-rend2/G2_gore_r2.h diff --git a/codemp/rd-rend2/MikkTSpace/README.md b/shared/rd-rend2/MikkTSpace/README.md similarity index 100% rename from codemp/rd-rend2/MikkTSpace/README.md rename to shared/rd-rend2/MikkTSpace/README.md diff --git a/codemp/rd-rend2/MikkTSpace/mikktspace.c b/shared/rd-rend2/MikkTSpace/mikktspace.c similarity index 100% rename from codemp/rd-rend2/MikkTSpace/mikktspace.c rename to shared/rd-rend2/MikkTSpace/mikktspace.c diff --git a/codemp/rd-rend2/MikkTSpace/mikktspace.h b/shared/rd-rend2/MikkTSpace/mikktspace.h similarity index 100% rename from codemp/rd-rend2/MikkTSpace/mikktspace.h rename to shared/rd-rend2/MikkTSpace/mikktspace.h diff --git a/codemp/rd-rend2/glext.h b/shared/rd-rend2/glext.h similarity index 90% rename from codemp/rd-rend2/glext.h rename to shared/rd-rend2/glext.h index 63ea7f2465..bd863204f4 100644 --- a/codemp/rd-rend2/glext.h +++ b/shared/rd-rend2/glext.h @@ -1,39 +1,18 @@ -#ifndef __glext_h_ -#define __glext_h_ 1 +#ifndef __gl_glext_h_ +#define __gl_glext_h_ 1 #ifdef __cplusplus extern "C" { #endif /* -** Copyright (c) 2013-2014 The Khronos Group Inc. +** Copyright 2013-2020 The Khronos Group Inc. +** SPDX-License-Identifier: MIT ** -** Permission is hereby granted, free of charge, to any person obtaining a -** copy of this software and/or associated documentation files (the -** "Materials"), to deal in the Materials without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Materials, and to -** permit persons to whom the Materials are furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be included -** in all copies or substantial portions of the Materials. -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -*/ -/* ** This header is generated from the Khronos OpenGL / OpenGL ES XML ** API Registry. The current version of the Registry, generator scripts ** used to make the header, and the header can be found at -** http://www.opengl.org/registry/ -** -** Khronos $Revision: 28986 $ on $Date: 2014-11-18 18:43:15 -0800 (Tue, 18 Nov 2014) $ +** https://github.com/KhronosGroup/OpenGL-Registry */ #if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) @@ -53,7 +32,9 @@ extern "C" { #define GLAPI extern #endif -#define GL_GLEXT_VERSION 20141118 +#define GL_GLEXT_VERSION 20240327 + +#include /* Generated C header for: * API: gl @@ -355,15 +336,17 @@ GLAPI void APIENTRY glMultTransposeMatrixd (const GLdouble *m); #define GL_TEXTURE_FILTER_CONTROL 0x8500 #define GL_DEPTH_TEXTURE_MODE 0x884B #define GL_COMPARE_R_TO_TEXTURE 0x884E -#define GL_FUNC_ADD 0x8006 -#define GL_FUNC_SUBTRACT 0x800A -#define GL_FUNC_REVERSE_SUBTRACT 0x800B -#define GL_MIN 0x8007 -#define GL_MAX 0x8008 +#define GL_BLEND_COLOR 0x8005 +#define GL_BLEND_EQUATION 0x8009 #define GL_CONSTANT_COLOR 0x8001 #define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 #define GL_CONSTANT_ALPHA 0x8003 #define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_FUNC_ADD 0x8006 +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_FUNC_SUBTRACT 0x800A +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei drawcount); typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei drawcount); @@ -464,9 +447,8 @@ GLAPI void APIENTRY glBlendEquation (GLenum mode); #ifndef GL_VERSION_1_5 #define GL_VERSION_1_5 1 -#include -typedef ptrdiff_t GLsizeiptr; -typedef ptrdiff_t GLintptr; +typedef khronos_ssize_t GLsizeiptr; +typedef khronos_intptr_t GLintptr; #define GL_BUFFER_SIZE 0x8764 #define GL_BUFFER_USAGE 0x8765 #define GL_QUERY_COUNTER_BITS 0x8864 @@ -879,7 +861,7 @@ GLAPI void APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboole #ifndef GL_VERSION_3_0 #define GL_VERSION_3_0 1 -typedef unsigned short GLhalf; +typedef khronos_uint16_t GLhalf; #define GL_COMPARE_REF_TO_TEXTURE 0x884E #define GL_CLIP_DISTANCE0 0x3000 #define GL_CLIP_DISTANCE1 0x3001 @@ -1041,6 +1023,22 @@ typedef unsigned short GLhalf; #define GL_COLOR_ATTACHMENT13 0x8CED #define GL_COLOR_ATTACHMENT14 0x8CEE #define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_COLOR_ATTACHMENT16 0x8CF0 +#define GL_COLOR_ATTACHMENT17 0x8CF1 +#define GL_COLOR_ATTACHMENT18 0x8CF2 +#define GL_COLOR_ATTACHMENT19 0x8CF3 +#define GL_COLOR_ATTACHMENT20 0x8CF4 +#define GL_COLOR_ATTACHMENT21 0x8CF5 +#define GL_COLOR_ATTACHMENT22 0x8CF6 +#define GL_COLOR_ATTACHMENT23 0x8CF7 +#define GL_COLOR_ATTACHMENT24 0x8CF8 +#define GL_COLOR_ATTACHMENT25 0x8CF9 +#define GL_COLOR_ATTACHMENT26 0x8CFA +#define GL_COLOR_ATTACHMENT27 0x8CFB +#define GL_COLOR_ATTACHMENT28 0x8CFC +#define GL_COLOR_ATTACHMENT29 0x8CFD +#define GL_COLOR_ATTACHMENT30 0x8CFE +#define GL_COLOR_ATTACHMENT31 0x8CFF #define GL_DEPTH_ATTACHMENT 0x8D00 #define GL_STENCIL_ATTACHMENT 0x8D20 #define GL_FRAMEBUFFER 0x8D40 @@ -1367,45 +1365,8 @@ GLAPI void APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIn #ifndef GL_VERSION_3_2 #define GL_VERSION_3_2 1 typedef struct __GLsync *GLsync; -#ifndef GLEXT_64_TYPES_DEFINED -/* This code block is duplicated in glxext.h, so must be protected */ -#define GLEXT_64_TYPES_DEFINED -/* Define int32_t, int64_t, and uint64_t types for UST/MSC */ -/* (as used in the GL_EXT_timer_query extension). */ -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -#include -#elif defined(__sun__) || defined(__digital__) -#include -#if defined(__STDC__) -#if defined(__arch64__) || defined(_LP64) -typedef long int int64_t; -typedef unsigned long int uint64_t; -#else -typedef long long int int64_t; -typedef unsigned long long int uint64_t; -#endif /* __arch64__ */ -#endif /* __STDC__ */ -#elif defined( __VMS ) || defined(__sgi) -#include -#elif defined(__SCO__) || defined(__USLC__) -#include -#elif defined(__UNIXOS2__) || defined(__SOL64__) -typedef long int int32_t; -typedef long long int int64_t; -typedef unsigned long long int uint64_t; -#elif defined(_WIN32) && defined(__GNUC__) -#include -#elif defined(_WIN32) -typedef __int32 int32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -#else -/* Fallback if nothing above works */ -#include -#endif -#endif -typedef uint64_t GLuint64; -typedef int64_t GLint64; +typedef khronos_uint64_t GLuint64; +typedef khronos_int64_t GLint64; #define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001 #define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 #define GL_LINES_ADJACENCY 0x000A @@ -1481,7 +1442,7 @@ typedef void (APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync); typedef GLenum (APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); typedef void (APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); typedef void (APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data); -typedef void (APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); +typedef void (APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei count, GLsizei *length, GLint *values); typedef void (APIENTRYP PFNGLGETINTEGER64I_VPROC) (GLenum target, GLuint index, GLint64 *data); typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERI64VPROC) (GLenum target, GLenum pname, GLint64 *params); typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); @@ -1501,7 +1462,7 @@ GLAPI void APIENTRY glDeleteSync (GLsync sync); GLAPI GLenum APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); GLAPI void APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); GLAPI void APIENTRY glGetInteger64v (GLenum pname, GLint64 *data); -GLAPI void APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); +GLAPI void APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei count, GLsizei *length, GLint *values); GLAPI void APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data); GLAPI void APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params); GLAPI void APIENTRY glFramebufferTexture (GLenum target, GLenum attachment, GLuint texture, GLint level); @@ -1757,8 +1718,8 @@ typedef void (APIENTRYP PFNGLGETUNIFORMDVPROC) (GLuint program, GLint location, typedef GLint (APIENTRYP PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) (GLuint program, GLenum shadertype, const GLchar *name); typedef GLuint (APIENTRYP PFNGLGETSUBROUTINEINDEXPROC) (GLuint program, GLenum shadertype, const GLchar *name); typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values); -typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name); -typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name); +typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); +typedef void (APIENTRYP PFNGLGETACTIVESUBROUTINENAMEPROC) (GLuint program, GLenum shadertype, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); typedef void (APIENTRYP PFNGLUNIFORMSUBROUTINESUIVPROC) (GLenum shadertype, GLsizei count, const GLuint *indices); typedef void (APIENTRYP PFNGLGETUNIFORMSUBROUTINEUIVPROC) (GLenum shadertype, GLint location, GLuint *params); typedef void (APIENTRYP PFNGLGETPROGRAMSTAGEIVPROC) (GLuint program, GLenum shadertype, GLenum pname, GLint *values); @@ -1804,8 +1765,8 @@ GLAPI void APIENTRY glGetUniformdv (GLuint program, GLint location, GLdouble *pa GLAPI GLint APIENTRY glGetSubroutineUniformLocation (GLuint program, GLenum shadertype, const GLchar *name); GLAPI GLuint APIENTRY glGetSubroutineIndex (GLuint program, GLenum shadertype, const GLchar *name); GLAPI void APIENTRY glGetActiveSubroutineUniformiv (GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint *values); -GLAPI void APIENTRY glGetActiveSubroutineUniformName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name); -GLAPI void APIENTRY glGetActiveSubroutineName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufsize, GLsizei *length, GLchar *name); +GLAPI void APIENTRY glGetActiveSubroutineUniformName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); +GLAPI void APIENTRY glGetActiveSubroutineName (GLuint program, GLenum shadertype, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); GLAPI void APIENTRY glUniformSubroutinesuiv (GLenum shadertype, GLsizei count, const GLuint *indices); GLAPI void APIENTRY glGetUniformSubroutineuiv (GLenum shadertype, GLint location, GLuint *params); GLAPI void APIENTRY glGetProgramStageiv (GLuint program, GLenum shadertype, GLenum pname, GLint *values); @@ -1863,7 +1824,7 @@ GLAPI void APIENTRY glGetQueryIndexediv (GLenum target, GLuint index, GLenum pna #define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F #define GL_UNDEFINED_VERTEX 0x8260 typedef void (APIENTRYP PFNGLRELEASESHADERCOMPILERPROC) (void); -typedef void (APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length); +typedef void (APIENTRYP PFNGLSHADERBINARYPROC) (GLsizei count, const GLuint *shaders, GLenum binaryFormat, const void *binary, GLsizei length); typedef void (APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC) (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); typedef void (APIENTRYP PFNGLDEPTHRANGEFPROC) (GLfloat n, GLfloat f); typedef void (APIENTRYP PFNGLCLEARDEPTHFPROC) (GLfloat d); @@ -1952,7 +1913,7 @@ typedef void (APIENTRYP PFNGLGETFLOATI_VPROC) (GLenum target, GLuint index, GLfl typedef void (APIENTRYP PFNGLGETDOUBLEI_VPROC) (GLenum target, GLuint index, GLdouble *data); #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glReleaseShaderCompiler (void); -GLAPI void APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length); +GLAPI void APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryFormat, const void *binary, GLsizei length); GLAPI void APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); GLAPI void APIENTRY glDepthRangef (GLfloat n, GLfloat f); GLAPI void APIENTRY glClearDepthf (GLfloat d); @@ -2159,7 +2120,7 @@ GLAPI void APIENTRY glGetDoublei_v (GLenum target, GLuint index, GLdouble *data) typedef void (APIENTRYP PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance); typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance); typedef void (APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance); -typedef void (APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params); +typedef void (APIENTRYP PFNGLGETINTERNALFORMATIVPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint *params); typedef void (APIENTRYP PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC) (GLuint program, GLuint bufferIndex, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); typedef void (APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers); @@ -2172,7 +2133,7 @@ typedef void (APIENTRYP PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC) (GLenum m GLAPI void APIENTRY glDrawArraysInstancedBaseInstance (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance); GLAPI void APIENTRY glDrawElementsInstancedBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance); GLAPI void APIENTRY glDrawElementsInstancedBaseVertexBaseInstance (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance); -GLAPI void APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params); +GLAPI void APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint *params); GLAPI void APIENTRY glGetActiveAtomicCounterBufferiv (GLuint program, GLuint bufferIndex, GLenum pname, GLint *params); GLAPI void APIENTRY glBindImageTexture (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); GLAPI void APIENTRY glMemoryBarrier (GLbitfield barriers); @@ -2453,7 +2414,7 @@ typedef void (APIENTRYP PFNGLDISPATCHCOMPUTEINDIRECTPROC) (GLintptr indirect); typedef void (APIENTRYP PFNGLCOPYIMAGESUBDATAPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); typedef void (APIENTRYP PFNGLFRAMEBUFFERPARAMETERIPROC) (GLenum target, GLenum pname, GLint param); typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETINTERNALFORMATI64VPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64 *params); +typedef void (APIENTRYP PFNGLGETINTERNALFORMATI64VPROC) (GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint64 *params); typedef void (APIENTRYP PFNGLINVALIDATETEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); typedef void (APIENTRYP PFNGLINVALIDATETEXIMAGEPROC) (GLuint texture, GLint level); typedef void (APIENTRYP PFNGLINVALIDATEBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length); @@ -2465,7 +2426,7 @@ typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum typedef void (APIENTRYP PFNGLGETPROGRAMINTERFACEIVPROC) (GLuint program, GLenum programInterface, GLenum pname, GLint *params); typedef GLuint (APIENTRYP PFNGLGETPROGRAMRESOURCEINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name); typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCENAMEPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); -typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params); +typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCEIVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei count, GLsizei *length, GLint *params); typedef GLint (APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONPROC) (GLuint program, GLenum programInterface, const GLchar *name); typedef GLint (APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC) (GLuint program, GLenum programInterface, const GLchar *name); typedef void (APIENTRYP PFNGLSHADERSTORAGEBLOCKBINDINGPROC) (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding); @@ -2497,7 +2458,7 @@ GLAPI void APIENTRY glDispatchComputeIndirect (GLintptr indirect); GLAPI void APIENTRY glCopyImageSubData (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); GLAPI void APIENTRY glFramebufferParameteri (GLenum target, GLenum pname, GLint param); GLAPI void APIENTRY glGetFramebufferParameteriv (GLenum target, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetInternalformati64v (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint64 *params); +GLAPI void APIENTRY glGetInternalformati64v (GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint64 *params); GLAPI void APIENTRY glInvalidateTexSubImage (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); GLAPI void APIENTRY glInvalidateTexImage (GLuint texture, GLint level); GLAPI void APIENTRY glInvalidateBufferSubData (GLuint buffer, GLintptr offset, GLsizeiptr length); @@ -2509,7 +2470,7 @@ GLAPI void APIENTRY glMultiDrawElementsIndirect (GLenum mode, GLenum type, const GLAPI void APIENTRY glGetProgramInterfaceiv (GLuint program, GLenum programInterface, GLenum pname, GLint *params); GLAPI GLuint APIENTRY glGetProgramResourceIndex (GLuint program, GLenum programInterface, const GLchar *name); GLAPI void APIENTRY glGetProgramResourceName (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); -GLAPI void APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params); +GLAPI void APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei count, GLsizei *length, GLint *params); GLAPI GLint APIENTRY glGetProgramResourceLocation (GLuint program, GLenum programInterface, const GLchar *name); GLAPI GLint APIENTRY glGetProgramResourceLocationIndex (GLuint program, GLenum programInterface, const GLchar *name); GLAPI void APIENTRY glShaderStorageBlockBinding (GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding); @@ -2594,7 +2555,6 @@ GLAPI void APIENTRY glBindVertexBuffers (GLuint first, GLsizei count, const GLui #define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES 0x82FA #define GL_TEXTURE_TARGET 0x1006 #define GL_QUERY_TARGET 0x82EA -#define GL_TEXTURE_BINDING 0x82EB #define GL_GUILTY_CONTEXT_RESET 0x8253 #define GL_INNOCENT_CONTEXT_RESET 0x8254 #define GL_UNKNOWN_CONTEXT_RESET 0x8255 @@ -2602,30 +2562,42 @@ GLAPI void APIENTRY glBindVertexBuffers (GLuint first, GLsizei count, const GLui #define GL_LOSE_CONTEXT_ON_RESET 0x8252 #define GL_NO_RESET_NOTIFICATION 0x8261 #define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004 +#define GL_COLOR_TABLE 0x80D0 +#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 +#define GL_PROXY_COLOR_TABLE 0x80D3 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 +#define GL_CONVOLUTION_1D 0x8010 +#define GL_CONVOLUTION_2D 0x8011 +#define GL_SEPARABLE_2D 0x8012 +#define GL_HISTOGRAM 0x8024 +#define GL_PROXY_HISTOGRAM 0x8025 +#define GL_MINMAX 0x802E #define GL_CONTEXT_RELEASE_BEHAVIOR 0x82FB #define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC typedef void (APIENTRYP PFNGLCLIPCONTROLPROC) (GLenum origin, GLenum depth); typedef void (APIENTRYP PFNGLCREATETRANSFORMFEEDBACKSPROC) (GLsizei n, GLuint *ids); typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC) (GLuint xfb, GLuint index, GLuint buffer); -typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC) (GLuint xfb, GLuint index, GLuint buffer, GLintptr offset, GLsizei size); +typedef void (APIENTRYP PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC) (GLuint xfb, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKIVPROC) (GLuint xfb, GLenum pname, GLint *param); typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint *param); typedef void (APIENTRYP PFNGLGETTRANSFORMFEEDBACKI64_VPROC) (GLuint xfb, GLenum pname, GLuint index, GLint64 *param); typedef void (APIENTRYP PFNGLCREATEBUFFERSPROC) (GLsizei n, GLuint *buffers); -typedef void (APIENTRYP PFNGLNAMEDBUFFERSTORAGEPROC) (GLuint buffer, GLsizei size, const void *data, GLbitfield flags); -typedef void (APIENTRYP PFNGLNAMEDBUFFERDATAPROC) (GLuint buffer, GLsizei size, const void *data, GLenum usage); -typedef void (APIENTRYP PFNGLNAMEDBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizei size, const void *data); -typedef void (APIENTRYP PFNGLCOPYNAMEDBUFFERSUBDATAPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizei size); +typedef void (APIENTRYP PFNGLNAMEDBUFFERSTORAGEPROC) (GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags); +typedef void (APIENTRYP PFNGLNAMEDBUFFERDATAPROC) (GLuint buffer, GLsizeiptr size, const void *data, GLenum usage); +typedef void (APIENTRYP PFNGLNAMEDBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data); +typedef void (APIENTRYP PFNGLCOPYNAMEDBUFFERSUBDATAPROC) (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERDATAPROC) (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data); -typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERSUBDATAPROC) (GLuint buffer, GLenum internalformat, GLintptr offset, GLsizei size, GLenum format, GLenum type, const void *data); +typedef void (APIENTRYP PFNGLCLEARNAMEDBUFFERSUBDATAPROC) (GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data); typedef void *(APIENTRYP PFNGLMAPNAMEDBUFFERPROC) (GLuint buffer, GLenum access); -typedef void *(APIENTRYP PFNGLMAPNAMEDBUFFERRANGEPROC) (GLuint buffer, GLintptr offset, GLsizei length, GLbitfield access); +typedef void *(APIENTRYP PFNGLMAPNAMEDBUFFERRANGEPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); typedef GLboolean (APIENTRYP PFNGLUNMAPNAMEDBUFFERPROC) (GLuint buffer); -typedef void (APIENTRYP PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC) (GLuint buffer, GLintptr offset, GLsizei length); +typedef void (APIENTRYP PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC) (GLuint buffer, GLintptr offset, GLsizeiptr length); typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERIVPROC) (GLuint buffer, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPARAMETERI64VPROC) (GLuint buffer, GLenum pname, GLint64 *params); typedef void (APIENTRYP PFNGLGETNAMEDBUFFERPOINTERVPROC) (GLuint buffer, GLenum pname, void **params); -typedef void (APIENTRYP PFNGLGETNAMEDBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizei size, void *data); +typedef void (APIENTRYP PFNGLGETNAMEDBUFFERSUBDATAPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, void *data); typedef void (APIENTRYP PFNGLCREATEFRAMEBUFFERSPROC) (GLsizei n, GLuint *framebuffers); typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC) (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC) (GLuint framebuffer, GLenum pname, GLint param); @@ -2639,7 +2611,7 @@ typedef void (APIENTRYP PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC) (GLuint fram typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERIVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint *value); typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint *value); typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERFVPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat *value); -typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERFIPROC) (GLuint framebuffer, GLenum buffer, const GLfloat depth, GLint stencil); +typedef void (APIENTRYP PFNGLCLEARNAMEDFRAMEBUFFERFIPROC) (GLuint framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); typedef void (APIENTRYP PFNGLBLITNAMEDFRAMEBUFFERPROC) (GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); typedef GLenum (APIENTRYP PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC) (GLuint framebuffer, GLenum target); typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC) (GLuint framebuffer, GLenum pname, GLint *param); @@ -2650,7 +2622,7 @@ typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC) (GLuint re typedef void (APIENTRYP PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC) (GLuint renderbuffer, GLenum pname, GLint *params); typedef void (APIENTRYP PFNGLCREATETEXTURESPROC) (GLenum target, GLsizei n, GLuint *textures); typedef void (APIENTRYP PFNGLTEXTUREBUFFERPROC) (GLuint texture, GLenum internalformat, GLuint buffer); -typedef void (APIENTRYP PFNGLTEXTUREBUFFERRANGEPROC) (GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizei size); +typedef void (APIENTRYP PFNGLTEXTUREBUFFERRANGEPROC) (GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); typedef void (APIENTRYP PFNGLTEXTURESTORAGE1DPROC) (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width); typedef void (APIENTRYP PFNGLTEXTURESTORAGE2DPROC) (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); typedef void (APIENTRYP PFNGLTEXTURESTORAGE3DPROC) (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); @@ -2730,25 +2702,25 @@ typedef void (APIENTRYP PFNGLTEXTUREBARRIERPROC) (void); GLAPI void APIENTRY glClipControl (GLenum origin, GLenum depth); GLAPI void APIENTRY glCreateTransformFeedbacks (GLsizei n, GLuint *ids); GLAPI void APIENTRY glTransformFeedbackBufferBase (GLuint xfb, GLuint index, GLuint buffer); -GLAPI void APIENTRY glTransformFeedbackBufferRange (GLuint xfb, GLuint index, GLuint buffer, GLintptr offset, GLsizei size); +GLAPI void APIENTRY glTransformFeedbackBufferRange (GLuint xfb, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); GLAPI void APIENTRY glGetTransformFeedbackiv (GLuint xfb, GLenum pname, GLint *param); GLAPI void APIENTRY glGetTransformFeedbacki_v (GLuint xfb, GLenum pname, GLuint index, GLint *param); GLAPI void APIENTRY glGetTransformFeedbacki64_v (GLuint xfb, GLenum pname, GLuint index, GLint64 *param); GLAPI void APIENTRY glCreateBuffers (GLsizei n, GLuint *buffers); -GLAPI void APIENTRY glNamedBufferStorage (GLuint buffer, GLsizei size, const void *data, GLbitfield flags); -GLAPI void APIENTRY glNamedBufferData (GLuint buffer, GLsizei size, const void *data, GLenum usage); -GLAPI void APIENTRY glNamedBufferSubData (GLuint buffer, GLintptr offset, GLsizei size, const void *data); -GLAPI void APIENTRY glCopyNamedBufferSubData (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizei size); +GLAPI void APIENTRY glNamedBufferStorage (GLuint buffer, GLsizeiptr size, const void *data, GLbitfield flags); +GLAPI void APIENTRY glNamedBufferData (GLuint buffer, GLsizeiptr size, const void *data, GLenum usage); +GLAPI void APIENTRY glNamedBufferSubData (GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data); +GLAPI void APIENTRY glCopyNamedBufferSubData (GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); GLAPI void APIENTRY glClearNamedBufferData (GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void *data); -GLAPI void APIENTRY glClearNamedBufferSubData (GLuint buffer, GLenum internalformat, GLintptr offset, GLsizei size, GLenum format, GLenum type, const void *data); +GLAPI void APIENTRY glClearNamedBufferSubData (GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void *data); GLAPI void *APIENTRY glMapNamedBuffer (GLuint buffer, GLenum access); -GLAPI void *APIENTRY glMapNamedBufferRange (GLuint buffer, GLintptr offset, GLsizei length, GLbitfield access); +GLAPI void *APIENTRY glMapNamedBufferRange (GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); GLAPI GLboolean APIENTRY glUnmapNamedBuffer (GLuint buffer); -GLAPI void APIENTRY glFlushMappedNamedBufferRange (GLuint buffer, GLintptr offset, GLsizei length); +GLAPI void APIENTRY glFlushMappedNamedBufferRange (GLuint buffer, GLintptr offset, GLsizeiptr length); GLAPI void APIENTRY glGetNamedBufferParameteriv (GLuint buffer, GLenum pname, GLint *params); GLAPI void APIENTRY glGetNamedBufferParameteri64v (GLuint buffer, GLenum pname, GLint64 *params); GLAPI void APIENTRY glGetNamedBufferPointerv (GLuint buffer, GLenum pname, void **params); -GLAPI void APIENTRY glGetNamedBufferSubData (GLuint buffer, GLintptr offset, GLsizei size, void *data); +GLAPI void APIENTRY glGetNamedBufferSubData (GLuint buffer, GLintptr offset, GLsizeiptr size, void *data); GLAPI void APIENTRY glCreateFramebuffers (GLsizei n, GLuint *framebuffers); GLAPI void APIENTRY glNamedFramebufferRenderbuffer (GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); GLAPI void APIENTRY glNamedFramebufferParameteri (GLuint framebuffer, GLenum pname, GLint param); @@ -2762,7 +2734,7 @@ GLAPI void APIENTRY glInvalidateNamedFramebufferSubData (GLuint framebuffer, GLs GLAPI void APIENTRY glClearNamedFramebufferiv (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint *value); GLAPI void APIENTRY glClearNamedFramebufferuiv (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint *value); GLAPI void APIENTRY glClearNamedFramebufferfv (GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat *value); -GLAPI void APIENTRY glClearNamedFramebufferfi (GLuint framebuffer, GLenum buffer, const GLfloat depth, GLint stencil); +GLAPI void APIENTRY glClearNamedFramebufferfi (GLuint framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); GLAPI void APIENTRY glBlitNamedFramebuffer (GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); GLAPI GLenum APIENTRY glCheckNamedFramebufferStatus (GLuint framebuffer, GLenum target); GLAPI void APIENTRY glGetNamedFramebufferParameteriv (GLuint framebuffer, GLenum pname, GLint *param); @@ -2773,7 +2745,7 @@ GLAPI void APIENTRY glNamedRenderbufferStorageMultisample (GLuint renderbuffer, GLAPI void APIENTRY glGetNamedRenderbufferParameteriv (GLuint renderbuffer, GLenum pname, GLint *params); GLAPI void APIENTRY glCreateTextures (GLenum target, GLsizei n, GLuint *textures); GLAPI void APIENTRY glTextureBuffer (GLuint texture, GLenum internalformat, GLuint buffer); -GLAPI void APIENTRY glTextureBufferRange (GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizei size); +GLAPI void APIENTRY glTextureBufferRange (GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); GLAPI void APIENTRY glTextureStorage1D (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width); GLAPI void APIENTRY glTextureStorage2D (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); GLAPI void APIENTRY glTextureStorage3D (GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); @@ -2852,6 +2824,42 @@ GLAPI void APIENTRY glTextureBarrier (void); #endif #endif /* GL_VERSION_4_5 */ +#ifndef GL_VERSION_4_6 +#define GL_VERSION_4_6 1 +#define GL_SHADER_BINARY_FORMAT_SPIR_V 0x9551 +#define GL_SPIR_V_BINARY 0x9552 +#define GL_PARAMETER_BUFFER 0x80EE +#define GL_PARAMETER_BUFFER_BINDING 0x80EF +#define GL_CONTEXT_FLAG_NO_ERROR_BIT 0x00000008 +#define GL_VERTICES_SUBMITTED 0x82EE +#define GL_PRIMITIVES_SUBMITTED 0x82EF +#define GL_VERTEX_SHADER_INVOCATIONS 0x82F0 +#define GL_TESS_CONTROL_SHADER_PATCHES 0x82F1 +#define GL_TESS_EVALUATION_SHADER_INVOCATIONS 0x82F2 +#define GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED 0x82F3 +#define GL_FRAGMENT_SHADER_INVOCATIONS 0x82F4 +#define GL_COMPUTE_SHADER_INVOCATIONS 0x82F5 +#define GL_CLIPPING_INPUT_PRIMITIVES 0x82F6 +#define GL_CLIPPING_OUTPUT_PRIMITIVES 0x82F7 +#define GL_POLYGON_OFFSET_CLAMP 0x8E1B +#define GL_SPIR_V_EXTENSIONS 0x9553 +#define GL_NUM_SPIR_V_EXTENSIONS 0x9554 +#define GL_TEXTURE_MAX_ANISOTROPY 0x84FE +#define GL_MAX_TEXTURE_MAX_ANISOTROPY 0x84FF +#define GL_TRANSFORM_FEEDBACK_OVERFLOW 0x82EC +#define GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW 0x82ED +typedef void (APIENTRYP PFNGLSPECIALIZESHADERPROC) (GLuint shader, const GLchar *pEntryPoint, GLuint numSpecializationConstants, const GLuint *pConstantIndex, const GLuint *pConstantValue); +typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC) (GLenum mode, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC) (GLenum mode, GLenum type, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +typedef void (APIENTRYP PFNGLPOLYGONOFFSETCLAMPPROC) (GLfloat factor, GLfloat units, GLfloat clamp); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glSpecializeShader (GLuint shader, const GLchar *pEntryPoint, GLuint numSpecializationConstants, const GLuint *pConstantIndex, const GLuint *pConstantValue); +GLAPI void APIENTRY glMultiDrawArraysIndirectCount (GLenum mode, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +GLAPI void APIENTRY glMultiDrawElementsIndirectCount (GLenum mode, GLenum type, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +GLAPI void APIENTRY glPolygonOffsetClamp (GLfloat factor, GLfloat units, GLfloat clamp); +#endif +#endif /* GL_VERSION_4_6 */ + #ifndef GL_ARB_ES2_compatibility #define GL_ARB_ES2_compatibility 1 #endif /* GL_ARB_ES2_compatibility */ @@ -2860,6 +2868,17 @@ GLAPI void APIENTRY glTextureBarrier (void); #define GL_ARB_ES3_1_compatibility 1 #endif /* GL_ARB_ES3_1_compatibility */ +#ifndef GL_ARB_ES3_2_compatibility +#define GL_ARB_ES3_2_compatibility 1 +#define GL_PRIMITIVE_BOUNDING_BOX_ARB 0x92BE +#define GL_MULTISAMPLE_LINE_WIDTH_RANGE_ARB 0x9381 +#define GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY_ARB 0x9382 +typedef void (APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXARBPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glPrimitiveBoundingBoxARB (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); +#endif +#endif /* GL_ARB_ES3_2_compatibility */ + #ifndef GL_ARB_ES3_compatibility #define GL_ARB_ES3_compatibility 1 #endif /* GL_ARB_ES3_compatibility */ @@ -2874,7 +2893,7 @@ GLAPI void APIENTRY glTextureBarrier (void); #ifndef GL_ARB_bindless_texture #define GL_ARB_bindless_texture 1 -typedef uint64_t GLuint64EXT; +typedef khronos_uint64_t GLuint64EXT; #define GL_UNSIGNED_INT64_ARB 0x140F typedef GLuint64 (APIENTRYP PFNGLGETTEXTUREHANDLEARBPROC) (GLuint texture); typedef GLuint64 (APIENTRYP PFNGLGETTEXTURESAMPLERHANDLEARBPROC) (GLuint texture, GLuint sampler); @@ -3273,6 +3292,10 @@ GLAPI GLboolean APIENTRY glIsProgramARB (GLuint program); #define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B #endif /* GL_ARB_fragment_shader */ +#ifndef GL_ARB_fragment_shader_interlock +#define GL_ARB_fragment_shader_interlock 1 +#endif /* GL_ARB_fragment_shader_interlock */ + #ifndef GL_ARB_framebuffer_no_attachments #define GL_ARB_framebuffer_no_attachments 1 #endif /* GL_ARB_framebuffer_no_attachments */ @@ -3325,6 +3348,16 @@ GLAPI void APIENTRY glFramebufferTextureFaceARB (GLenum target, GLenum attachmen #define GL_ARB_get_texture_sub_image 1 #endif /* GL_ARB_get_texture_sub_image */ +#ifndef GL_ARB_gl_spirv +#define GL_ARB_gl_spirv 1 +#define GL_SHADER_BINARY_FORMAT_SPIR_V_ARB 0x9551 +#define GL_SPIR_V_BINARY_ARB 0x9552 +typedef void (APIENTRYP PFNGLSPECIALIZESHADERARBPROC) (GLuint shader, const GLchar *pEntryPoint, GLuint numSpecializationConstants, const GLuint *pConstantIndex, const GLuint *pConstantValue); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glSpecializeShaderARB (GLuint shader, const GLchar *pEntryPoint, GLuint numSpecializationConstants, const GLuint *pConstantIndex, const GLuint *pConstantValue); +#endif +#endif /* GL_ARB_gl_spirv */ + #ifndef GL_ARB_gpu_shader5 #define GL_ARB_gpu_shader5 1 #endif /* GL_ARB_gpu_shader5 */ @@ -3333,9 +3366,94 @@ GLAPI void APIENTRY glFramebufferTextureFaceARB (GLenum target, GLenum attachmen #define GL_ARB_gpu_shader_fp64 1 #endif /* GL_ARB_gpu_shader_fp64 */ +#ifndef GL_ARB_gpu_shader_int64 +#define GL_ARB_gpu_shader_int64 1 +#define GL_INT64_ARB 0x140E +#define GL_INT64_VEC2_ARB 0x8FE9 +#define GL_INT64_VEC3_ARB 0x8FEA +#define GL_INT64_VEC4_ARB 0x8FEB +#define GL_UNSIGNED_INT64_VEC2_ARB 0x8FF5 +#define GL_UNSIGNED_INT64_VEC3_ARB 0x8FF6 +#define GL_UNSIGNED_INT64_VEC4_ARB 0x8FF7 +typedef void (APIENTRYP PFNGLUNIFORM1I64ARBPROC) (GLint location, GLint64 x); +typedef void (APIENTRYP PFNGLUNIFORM2I64ARBPROC) (GLint location, GLint64 x, GLint64 y); +typedef void (APIENTRYP PFNGLUNIFORM3I64ARBPROC) (GLint location, GLint64 x, GLint64 y, GLint64 z); +typedef void (APIENTRYP PFNGLUNIFORM4I64ARBPROC) (GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w); +typedef void (APIENTRYP PFNGLUNIFORM1I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value); +typedef void (APIENTRYP PFNGLUNIFORM2I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value); +typedef void (APIENTRYP PFNGLUNIFORM3I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value); +typedef void (APIENTRYP PFNGLUNIFORM4I64VARBPROC) (GLint location, GLsizei count, const GLint64 *value); +typedef void (APIENTRYP PFNGLUNIFORM1UI64ARBPROC) (GLint location, GLuint64 x); +typedef void (APIENTRYP PFNGLUNIFORM2UI64ARBPROC) (GLint location, GLuint64 x, GLuint64 y); +typedef void (APIENTRYP PFNGLUNIFORM3UI64ARBPROC) (GLint location, GLuint64 x, GLuint64 y, GLuint64 z); +typedef void (APIENTRYP PFNGLUNIFORM4UI64ARBPROC) (GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w); +typedef void (APIENTRYP PFNGLUNIFORM1UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value); +typedef void (APIENTRYP PFNGLUNIFORM2UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value); +typedef void (APIENTRYP PFNGLUNIFORM3UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value); +typedef void (APIENTRYP PFNGLUNIFORM4UI64VARBPROC) (GLint location, GLsizei count, const GLuint64 *value); +typedef void (APIENTRYP PFNGLGETUNIFORMI64VARBPROC) (GLuint program, GLint location, GLint64 *params); +typedef void (APIENTRYP PFNGLGETUNIFORMUI64VARBPROC) (GLuint program, GLint location, GLuint64 *params); +typedef void (APIENTRYP PFNGLGETNUNIFORMI64VARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLint64 *params); +typedef void (APIENTRYP PFNGLGETNUNIFORMUI64VARBPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint64 *params); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64ARBPROC) (GLuint program, GLint location, GLint64 x); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64ARBPROC) (GLuint program, GLint location, GLint64 x, GLint64 y); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64ARBPROC) (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64ARBPROC) (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4I64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLint64 *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64ARBPROC) (GLuint program, GLint location, GLuint64 x); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64ARBPROC) (GLuint program, GLint location, GLuint64 x, GLuint64 y); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64ARBPROC) (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64ARBPROC) (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM1UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM2UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM3UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value); +typedef void (APIENTRYP PFNGLPROGRAMUNIFORM4UI64VARBPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *value); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glUniform1i64ARB (GLint location, GLint64 x); +GLAPI void APIENTRY glUniform2i64ARB (GLint location, GLint64 x, GLint64 y); +GLAPI void APIENTRY glUniform3i64ARB (GLint location, GLint64 x, GLint64 y, GLint64 z); +GLAPI void APIENTRY glUniform4i64ARB (GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w); +GLAPI void APIENTRY glUniform1i64vARB (GLint location, GLsizei count, const GLint64 *value); +GLAPI void APIENTRY glUniform2i64vARB (GLint location, GLsizei count, const GLint64 *value); +GLAPI void APIENTRY glUniform3i64vARB (GLint location, GLsizei count, const GLint64 *value); +GLAPI void APIENTRY glUniform4i64vARB (GLint location, GLsizei count, const GLint64 *value); +GLAPI void APIENTRY glUniform1ui64ARB (GLint location, GLuint64 x); +GLAPI void APIENTRY glUniform2ui64ARB (GLint location, GLuint64 x, GLuint64 y); +GLAPI void APIENTRY glUniform3ui64ARB (GLint location, GLuint64 x, GLuint64 y, GLuint64 z); +GLAPI void APIENTRY glUniform4ui64ARB (GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w); +GLAPI void APIENTRY glUniform1ui64vARB (GLint location, GLsizei count, const GLuint64 *value); +GLAPI void APIENTRY glUniform2ui64vARB (GLint location, GLsizei count, const GLuint64 *value); +GLAPI void APIENTRY glUniform3ui64vARB (GLint location, GLsizei count, const GLuint64 *value); +GLAPI void APIENTRY glUniform4ui64vARB (GLint location, GLsizei count, const GLuint64 *value); +GLAPI void APIENTRY glGetUniformi64vARB (GLuint program, GLint location, GLint64 *params); +GLAPI void APIENTRY glGetUniformui64vARB (GLuint program, GLint location, GLuint64 *params); +GLAPI void APIENTRY glGetnUniformi64vARB (GLuint program, GLint location, GLsizei bufSize, GLint64 *params); +GLAPI void APIENTRY glGetnUniformui64vARB (GLuint program, GLint location, GLsizei bufSize, GLuint64 *params); +GLAPI void APIENTRY glProgramUniform1i64ARB (GLuint program, GLint location, GLint64 x); +GLAPI void APIENTRY glProgramUniform2i64ARB (GLuint program, GLint location, GLint64 x, GLint64 y); +GLAPI void APIENTRY glProgramUniform3i64ARB (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z); +GLAPI void APIENTRY glProgramUniform4i64ARB (GLuint program, GLint location, GLint64 x, GLint64 y, GLint64 z, GLint64 w); +GLAPI void APIENTRY glProgramUniform1i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value); +GLAPI void APIENTRY glProgramUniform2i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value); +GLAPI void APIENTRY glProgramUniform3i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value); +GLAPI void APIENTRY glProgramUniform4i64vARB (GLuint program, GLint location, GLsizei count, const GLint64 *value); +GLAPI void APIENTRY glProgramUniform1ui64ARB (GLuint program, GLint location, GLuint64 x); +GLAPI void APIENTRY glProgramUniform2ui64ARB (GLuint program, GLint location, GLuint64 x, GLuint64 y); +GLAPI void APIENTRY glProgramUniform3ui64ARB (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z); +GLAPI void APIENTRY glProgramUniform4ui64ARB (GLuint program, GLint location, GLuint64 x, GLuint64 y, GLuint64 z, GLuint64 w); +GLAPI void APIENTRY glProgramUniform1ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value); +GLAPI void APIENTRY glProgramUniform2ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value); +GLAPI void APIENTRY glProgramUniform3ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value); +GLAPI void APIENTRY glProgramUniform4ui64vARB (GLuint program, GLint location, GLsizei count, const GLuint64 *value); +#endif +#endif /* GL_ARB_gpu_shader_int64 */ + #ifndef GL_ARB_half_float_pixel #define GL_ARB_half_float_pixel 1 -typedef unsigned short GLhalfARB; +typedef khronos_uint16_t GLhalfARB; #define GL_HALF_FLOAT_ARB 0x140B #endif /* GL_ARB_half_float_pixel */ @@ -3345,11 +3463,6 @@ typedef unsigned short GLhalfARB; #ifndef GL_ARB_imaging #define GL_ARB_imaging 1 -#define GL_BLEND_COLOR 0x8005 -#define GL_BLEND_EQUATION 0x8009 -#define GL_CONVOLUTION_1D 0x8010 -#define GL_CONVOLUTION_2D 0x8011 -#define GL_SEPARABLE_2D 0x8012 #define GL_CONVOLUTION_BORDER_MODE 0x8013 #define GL_CONVOLUTION_FILTER_SCALE 0x8014 #define GL_CONVOLUTION_FILTER_BIAS 0x8015 @@ -3367,8 +3480,6 @@ typedef unsigned short GLhalfARB; #define GL_POST_CONVOLUTION_GREEN_BIAS 0x8021 #define GL_POST_CONVOLUTION_BLUE_BIAS 0x8022 #define GL_POST_CONVOLUTION_ALPHA_BIAS 0x8023 -#define GL_HISTOGRAM 0x8024 -#define GL_PROXY_HISTOGRAM 0x8025 #define GL_HISTOGRAM_WIDTH 0x8026 #define GL_HISTOGRAM_FORMAT 0x8027 #define GL_HISTOGRAM_RED_SIZE 0x8028 @@ -3377,7 +3488,6 @@ typedef unsigned short GLhalfARB; #define GL_HISTOGRAM_ALPHA_SIZE 0x802B #define GL_HISTOGRAM_LUMINANCE_SIZE 0x802C #define GL_HISTOGRAM_SINK 0x802D -#define GL_MINMAX 0x802E #define GL_MINMAX_FORMAT 0x802F #define GL_MINMAX_SINK 0x8030 #define GL_TABLE_TOO_LARGE 0x8031 @@ -3392,12 +3502,6 @@ typedef unsigned short GLhalfARB; #define GL_POST_COLOR_MATRIX_GREEN_BIAS 0x80B9 #define GL_POST_COLOR_MATRIX_BLUE_BIAS 0x80BA #define GL_POST_COLOR_MATRIX_ALPHA_BIAS 0x80BB -#define GL_COLOR_TABLE 0x80D0 -#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 -#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 -#define GL_PROXY_COLOR_TABLE 0x80D3 -#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 -#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 #define GL_COLOR_TABLE_SCALE 0x80D6 #define GL_COLOR_TABLE_BIAS 0x80D7 #define GL_COLOR_TABLE_FORMAT 0x80D8 @@ -3483,11 +3587,11 @@ GLAPI void APIENTRY glResetMinmax (GLenum target); #define GL_ARB_indirect_parameters 1 #define GL_PARAMETER_BUFFER_ARB 0x80EE #define GL_PARAMETER_BUFFER_BINDING_ARB 0x80EF -typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC) (GLenum mode, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); -typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC) (GLenum mode, GLenum type, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTCOUNTARBPROC) (GLenum mode, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTARBPROC) (GLenum mode, GLenum type, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); #ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glMultiDrawArraysIndirectCountARB (GLenum mode, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); -GLAPI void APIENTRY glMultiDrawElementsIndirectCountARB (GLenum mode, GLenum type, GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +GLAPI void APIENTRY glMultiDrawArraysIndirectCountARB (GLenum mode, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +GLAPI void APIENTRY glMultiDrawElementsIndirectCountARB (GLenum mode, GLenum type, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); #endif #endif /* GL_ARB_indirect_parameters */ @@ -3507,6 +3611,25 @@ GLAPI void APIENTRY glVertexAttribDivisorARB (GLuint index, GLuint divisor); #ifndef GL_ARB_internalformat_query2 #define GL_ARB_internalformat_query2 1 #define GL_SRGB_DECODE_ARB 0x8299 +#define GL_VIEW_CLASS_EAC_R11 0x9383 +#define GL_VIEW_CLASS_EAC_RG11 0x9384 +#define GL_VIEW_CLASS_ETC2_RGB 0x9385 +#define GL_VIEW_CLASS_ETC2_RGBA 0x9386 +#define GL_VIEW_CLASS_ETC2_EAC_RGBA 0x9387 +#define GL_VIEW_CLASS_ASTC_4x4_RGBA 0x9388 +#define GL_VIEW_CLASS_ASTC_5x4_RGBA 0x9389 +#define GL_VIEW_CLASS_ASTC_5x5_RGBA 0x938A +#define GL_VIEW_CLASS_ASTC_6x5_RGBA 0x938B +#define GL_VIEW_CLASS_ASTC_6x6_RGBA 0x938C +#define GL_VIEW_CLASS_ASTC_8x5_RGBA 0x938D +#define GL_VIEW_CLASS_ASTC_8x6_RGBA 0x938E +#define GL_VIEW_CLASS_ASTC_8x8_RGBA 0x938F +#define GL_VIEW_CLASS_ASTC_10x5_RGBA 0x9390 +#define GL_VIEW_CLASS_ASTC_10x6_RGBA 0x9391 +#define GL_VIEW_CLASS_ASTC_10x8_RGBA 0x9392 +#define GL_VIEW_CLASS_ASTC_10x10_RGBA 0x9393 +#define GL_VIEW_CLASS_ASTC_12x10_RGBA 0x9394 +#define GL_VIEW_CLASS_ASTC_12x12_RGBA 0x9395 #endif /* GL_ARB_internalformat_query2 */ #ifndef GL_ARB_invalidate_subdata @@ -3712,6 +3835,16 @@ GLAPI void APIENTRY glGetQueryObjectuivARB (GLuint id, GLenum pname, GLuint *par #define GL_ARB_occlusion_query2 1 #endif /* GL_ARB_occlusion_query2 */ +#ifndef GL_ARB_parallel_shader_compile +#define GL_ARB_parallel_shader_compile 1 +#define GL_MAX_SHADER_COMPILER_THREADS_ARB 0x91B0 +#define GL_COMPLETION_STATUS_ARB 0x91B1 +typedef void (APIENTRYP PFNGLMAXSHADERCOMPILERTHREADSARBPROC) (GLuint count); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMaxShaderCompilerThreadsARB (GLuint count); +#endif +#endif /* GL_ARB_parallel_shader_compile */ + #ifndef GL_ARB_pipeline_statistics_query #define GL_ARB_pipeline_statistics_query 1 #define GL_VERTICES_SUBMITTED_ARB 0x82EE @@ -3754,6 +3887,14 @@ GLAPI void APIENTRY glPointParameterfvARB (GLenum pname, const GLfloat *params); #define GL_COORD_REPLACE_ARB 0x8862 #endif /* GL_ARB_point_sprite */ +#ifndef GL_ARB_polygon_offset_clamp +#define GL_ARB_polygon_offset_clamp 1 +#endif /* GL_ARB_polygon_offset_clamp */ + +#ifndef GL_ARB_post_depth_coverage +#define GL_ARB_post_depth_coverage 1 +#endif /* GL_ARB_post_depth_coverage */ + #ifndef GL_ARB_program_interface_query #define GL_ARB_program_interface_query 1 #endif /* GL_ARB_program_interface_query */ @@ -3827,6 +3968,26 @@ GLAPI void APIENTRY glGetnMinmaxARB (GLenum target, GLboolean reset, GLenum form #define GL_ARB_robustness_isolation 1 #endif /* GL_ARB_robustness_isolation */ +#ifndef GL_ARB_sample_locations +#define GL_ARB_sample_locations 1 +#define GL_SAMPLE_LOCATION_SUBPIXEL_BITS_ARB 0x933D +#define GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_ARB 0x933E +#define GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_ARB 0x933F +#define GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_ARB 0x9340 +#define GL_SAMPLE_LOCATION_ARB 0x8E50 +#define GL_PROGRAMMABLE_SAMPLE_LOCATION_ARB 0x9341 +#define GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_ARB 0x9342 +#define GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_ARB 0x9343 +typedef void (APIENTRYP PFNGLFRAMEBUFFERSAMPLELOCATIONSFVARBPROC) (GLenum target, GLuint start, GLsizei count, const GLfloat *v); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERSAMPLELOCATIONSFVARBPROC) (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v); +typedef void (APIENTRYP PFNGLEVALUATEDEPTHVALUESARBPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFramebufferSampleLocationsfvARB (GLenum target, GLuint start, GLsizei count, const GLfloat *v); +GLAPI void APIENTRY glNamedFramebufferSampleLocationsfvARB (GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v); +GLAPI void APIENTRY glEvaluateDepthValuesARB (void); +#endif +#endif /* GL_ARB_sample_locations */ + #ifndef GL_ARB_sample_shading #define GL_ARB_sample_shading 1 #define GL_SAMPLE_SHADING_ARB 0x8C36 @@ -3853,14 +4014,26 @@ GLAPI void APIENTRY glMinSampleShadingARB (GLfloat value); #define GL_ARB_separate_shader_objects 1 #endif /* GL_ARB_separate_shader_objects */ +#ifndef GL_ARB_shader_atomic_counter_ops +#define GL_ARB_shader_atomic_counter_ops 1 +#endif /* GL_ARB_shader_atomic_counter_ops */ + #ifndef GL_ARB_shader_atomic_counters #define GL_ARB_shader_atomic_counters 1 #endif /* GL_ARB_shader_atomic_counters */ +#ifndef GL_ARB_shader_ballot +#define GL_ARB_shader_ballot 1 +#endif /* GL_ARB_shader_ballot */ + #ifndef GL_ARB_shader_bit_encoding #define GL_ARB_shader_bit_encoding 1 #endif /* GL_ARB_shader_bit_encoding */ +#ifndef GL_ARB_shader_clock +#define GL_ARB_shader_clock 1 +#endif /* GL_ARB_shader_clock */ + #ifndef GL_ARB_shader_draw_parameters #define GL_ARB_shader_draw_parameters 1 #endif /* GL_ARB_shader_draw_parameters */ @@ -4025,6 +4198,10 @@ GLAPI void APIENTRY glGetShaderSourceARB (GLhandleARB obj, GLsizei maxLength, GL #define GL_ARB_shader_texture_lod 1 #endif /* GL_ARB_shader_texture_lod */ +#ifndef GL_ARB_shader_viewport_layer_array +#define GL_ARB_shader_viewport_layer_array 1 +#endif /* GL_ARB_shader_viewport_layer_array */ + #ifndef GL_ARB_shading_language_100 #define GL_ARB_shading_language_100 1 #define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C @@ -4098,12 +4275,24 @@ GLAPI void APIENTRY glNamedBufferPageCommitmentARB (GLuint buffer, GLintptr offs #define GL_MAX_SPARSE_3D_TEXTURE_SIZE_ARB 0x9199 #define GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_ARB 0x919A #define GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_ARB 0x91A9 -typedef void (APIENTRYP PFNGLTEXPAGECOMMITMENTARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident); +typedef void (APIENTRYP PFNGLTEXPAGECOMMITMENTARBPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit); #ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glTexPageCommitmentARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident); +GLAPI void APIENTRY glTexPageCommitmentARB (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit); #endif #endif /* GL_ARB_sparse_texture */ +#ifndef GL_ARB_sparse_texture2 +#define GL_ARB_sparse_texture2 1 +#endif /* GL_ARB_sparse_texture2 */ + +#ifndef GL_ARB_sparse_texture_clamp +#define GL_ARB_sparse_texture_clamp 1 +#endif /* GL_ARB_sparse_texture_clamp */ + +#ifndef GL_ARB_spirv_extensions +#define GL_ARB_spirv_extensions 1 +#endif /* GL_ARB_spirv_extensions */ + #ifndef GL_ARB_stencil_texturing #define GL_ARB_stencil_texturing 1 #endif /* GL_ARB_stencil_texturing */ @@ -4256,6 +4445,16 @@ GLAPI void APIENTRY glGetCompressedTexImageARB (GLenum target, GLint level, void #define GL_DOT3_RGBA_ARB 0x86AF #endif /* GL_ARB_texture_env_dot3 */ +#ifndef GL_ARB_texture_filter_anisotropic +#define GL_ARB_texture_filter_anisotropic 1 +#endif /* GL_ARB_texture_filter_anisotropic */ + +#ifndef GL_ARB_texture_filter_minmax +#define GL_ARB_texture_filter_minmax 1 +#define GL_TEXTURE_REDUCTION_MODE_ARB 0x9366 +#define GL_WEIGHTED_AVERAGE_ARB 0x9367 +#endif /* GL_ARB_texture_filter_minmax */ + #ifndef GL_ARB_texture_float #define GL_ARB_texture_float 1 #define GL_TEXTURE_RED_TYPE_ARB 0x8C10 @@ -4478,11 +4677,8 @@ GLAPI void APIENTRY glVertexBlendARB (GLint count); #ifndef GL_ARB_vertex_buffer_object #define GL_ARB_vertex_buffer_object 1 -// Unfortunate problem with the OS X SDK which defines these types incorrectly -#if !defined(MACOS_X) -typedef ptrdiff_t GLsizeiptrARB; -typedef ptrdiff_t GLintptrARB; -#endif +typedef khronos_ssize_t GLsizeiptrARB; +typedef khronos_intptr_t GLintptrARB; #define GL_BUFFER_SIZE_ARB 0x8764 #define GL_BUFFER_USAGE_ARB 0x8765 #define GL_ARRAY_BUFFER_ARB 0x8892 @@ -4677,6 +4873,12 @@ GLAPI GLint APIENTRY glGetAttribLocationARB (GLhandleARB programObj, const GLcha #ifndef GL_ARB_viewport_array #define GL_ARB_viewport_array 1 +typedef void (APIENTRYP PFNGLDEPTHRANGEARRAYDVNVPROC) (GLuint first, GLsizei count, const GLdouble *v); +typedef void (APIENTRYP PFNGLDEPTHRANGEINDEXEDDNVPROC) (GLuint index, GLdouble n, GLdouble f); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDepthRangeArraydvNV (GLuint first, GLsizei count, const GLdouble *v); +GLAPI void APIENTRY glDepthRangeIndexeddNV (GLuint index, GLdouble n, GLdouble f); +#endif #endif /* GL_ARB_viewport_array */ #ifndef GL_ARB_window_pos @@ -4753,6 +4955,21 @@ GLAPI void APIENTRY glBlendBarrierKHR (void); #define GL_KHR_debug 1 #endif /* GL_KHR_debug */ +#ifndef GL_KHR_no_error +#define GL_KHR_no_error 1 +#define GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR 0x00000008 +#endif /* GL_KHR_no_error */ + +#ifndef GL_KHR_parallel_shader_compile +#define GL_KHR_parallel_shader_compile 1 +#define GL_MAX_SHADER_COMPILER_THREADS_KHR 0x91B0 +#define GL_COMPLETION_STATUS_KHR 0x91B1 +typedef void (APIENTRYP PFNGLMAXSHADERCOMPILERTHREADSKHRPROC) (GLuint count); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glMaxShaderCompilerThreadsKHR (GLuint count); +#endif +#endif /* GL_KHR_parallel_shader_compile */ + #ifndef GL_KHR_robust_buffer_access_behavior #define GL_KHR_robust_buffer_access_behavior 1 #endif /* GL_KHR_robust_buffer_access_behavior */ @@ -4762,6 +4979,22 @@ GLAPI void APIENTRY glBlendBarrierKHR (void); #define GL_CONTEXT_ROBUST_ACCESS 0x90F3 #endif /* GL_KHR_robustness */ +#ifndef GL_KHR_shader_subgroup +#define GL_KHR_shader_subgroup 1 +#define GL_SUBGROUP_SIZE_KHR 0x9532 +#define GL_SUBGROUP_SUPPORTED_STAGES_KHR 0x9533 +#define GL_SUBGROUP_SUPPORTED_FEATURES_KHR 0x9534 +#define GL_SUBGROUP_QUAD_ALL_STAGES_KHR 0x9535 +#define GL_SUBGROUP_FEATURE_BASIC_BIT_KHR 0x00000001 +#define GL_SUBGROUP_FEATURE_VOTE_BIT_KHR 0x00000002 +#define GL_SUBGROUP_FEATURE_ARITHMETIC_BIT_KHR 0x00000004 +#define GL_SUBGROUP_FEATURE_BALLOT_BIT_KHR 0x00000008 +#define GL_SUBGROUP_FEATURE_SHUFFLE_BIT_KHR 0x00000010 +#define GL_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT_KHR 0x00000020 +#define GL_SUBGROUP_FEATURE_CLUSTERED_BIT_KHR 0x00000040 +#define GL_SUBGROUP_FEATURE_QUAD_BIT_KHR 0x00000080 +#endif /* GL_KHR_shader_subgroup */ + #ifndef GL_KHR_texture_compression_astc_hdr #define GL_KHR_texture_compression_astc_hdr 1 #define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 @@ -4798,6 +5031,10 @@ GLAPI void APIENTRY glBlendBarrierKHR (void); #define GL_KHR_texture_compression_astc_ldr 1 #endif /* GL_KHR_texture_compression_astc_ldr */ +#ifndef GL_KHR_texture_compression_astc_sliced_3d +#define GL_KHR_texture_compression_astc_sliced_3d 1 +#endif /* GL_KHR_texture_compression_astc_sliced_3d */ + #ifndef GL_OES_byte_coordinates #define GL_OES_byte_coordinates 1 typedef void (APIENTRYP PFNGLMULTITEXCOORD1BOESPROC) (GLenum texture, GLbyte s); @@ -4864,7 +5101,7 @@ GLAPI void APIENTRY glVertex4bvOES (const GLbyte *coords); #ifndef GL_OES_fixed_point #define GL_OES_fixed_point 1 -typedef GLint GLfixed; +typedef khronos_int32_t GLfixed; #define GL_FIXED_OES 0x140C typedef void (APIENTRYP PFNGLALPHAFUNCXOESPROC) (GLenum func, GLfixed ref); typedef void (APIENTRYP PFNGLCLEARCOLORXOESPROC) (GLfixed red, GLfixed green, GLfixed blue, GLfixed alpha); @@ -4895,7 +5132,6 @@ typedef void (APIENTRYP PFNGLPOINTPARAMETERXVOESPROC) (GLenum pname, const GLfix typedef void (APIENTRYP PFNGLPOINTSIZEXOESPROC) (GLfixed size); typedef void (APIENTRYP PFNGLPOLYGONOFFSETXOESPROC) (GLfixed factor, GLfixed units); typedef void (APIENTRYP PFNGLROTATEXOESPROC) (GLfixed angle, GLfixed x, GLfixed y, GLfixed z); -typedef void (APIENTRYP PFNGLSAMPLECOVERAGEOESPROC) (GLfixed value, GLboolean invert); typedef void (APIENTRYP PFNGLSCALEXOESPROC) (GLfixed x, GLfixed y, GLfixed z); typedef void (APIENTRYP PFNGLTEXENVXOESPROC) (GLenum target, GLenum pname, GLfixed param); typedef void (APIENTRYP PFNGLTEXENVXVOESPROC) (GLenum target, GLenum pname, const GLfixed *params); @@ -5000,7 +5236,6 @@ GLAPI void APIENTRY glPointParameterxvOES (GLenum pname, const GLfixed *params); GLAPI void APIENTRY glPointSizexOES (GLfixed size); GLAPI void APIENTRY glPolygonOffsetxOES (GLfixed factor, GLfixed units); GLAPI void APIENTRY glRotatexOES (GLfixed angle, GLfixed x, GLfixed y, GLfixed z); -GLAPI void APIENTRY glSampleCoverageOES (GLfixed value, GLboolean invert); GLAPI void APIENTRY glScalexOES (GLfixed x, GLfixed y, GLfixed z); GLAPI void APIENTRY glTexEnvxOES (GLenum target, GLenum pname, GLfixed param); GLAPI void APIENTRY glTexEnvxvOES (GLenum target, GLenum pname, const GLfixed *params); @@ -5162,12 +5397,12 @@ typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severi typedef void (APIENTRYP PFNGLDEBUGMESSAGEENABLEAMDPROC) (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); typedef void (APIENTRYP PFNGLDEBUGMESSAGEINSERTAMDPROC) (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf); typedef void (APIENTRYP PFNGLDEBUGMESSAGECALLBACKAMDPROC) (GLDEBUGPROCAMD callback, void *userParam); -typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufsize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message); +typedef GLuint (APIENTRYP PFNGLGETDEBUGMESSAGELOGAMDPROC) (GLuint count, GLsizei bufSize, GLenum *categories, GLenum *severities, GLuint *ids, GLsizei *lengths, GLchar *message); #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glDebugMessageEnableAMD (GLenum category, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); GLAPI void APIENTRY glDebugMessageInsertAMD (GLenum category, GLenum severity, GLuint id, GLsizei length, const GLchar *buf); GLAPI void APIENTRY glDebugMessageCallbackAMD (GLDEBUGPROCAMD callback, void *userParam); -GLAPI GLuint APIENTRY glGetDebugMessageLogAMD (GLuint count, GLsizei bufsize, GLenum *categories, GLuint *severities, GLuint *ids, GLsizei *lengths, GLchar *message); +GLAPI GLuint APIENTRY glGetDebugMessageLogAMD (GLuint count, GLsizei bufSize, GLenum *categories, GLenum *severities, GLuint *ids, GLsizei *lengths, GLchar *message); #endif #endif /* GL_AMD_debug_output */ @@ -5191,13 +5426,68 @@ GLAPI void APIENTRY glBlendEquationSeparateIndexedAMD (GLuint buf, GLenum modeRG #endif #endif /* GL_AMD_draw_buffers_blend */ +#ifndef GL_AMD_framebuffer_multisample_advanced +#define GL_AMD_framebuffer_multisample_advanced 1 +#define GL_RENDERBUFFER_STORAGE_SAMPLES_AMD 0x91B2 +#define GL_MAX_COLOR_FRAMEBUFFER_SAMPLES_AMD 0x91B3 +#define GL_MAX_COLOR_FRAMEBUFFER_STORAGE_SAMPLES_AMD 0x91B4 +#define GL_MAX_DEPTH_STENCIL_FRAMEBUFFER_SAMPLES_AMD 0x91B5 +#define GL_NUM_SUPPORTED_MULTISAMPLE_MODES_AMD 0x91B6 +#define GL_SUPPORTED_MULTISAMPLE_MODES_AMD 0x91B7 +typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEADVANCEDAMDPROC) (GLenum target, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEADVANCEDAMDPROC) (GLuint renderbuffer, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glRenderbufferStorageMultisampleAdvancedAMD (GLenum target, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glNamedRenderbufferStorageMultisampleAdvancedAMD (GLuint renderbuffer, GLsizei samples, GLsizei storageSamples, GLenum internalformat, GLsizei width, GLsizei height); +#endif +#endif /* GL_AMD_framebuffer_multisample_advanced */ + +#ifndef GL_AMD_framebuffer_sample_positions +#define GL_AMD_framebuffer_sample_positions 1 +#define GL_SUBSAMPLE_DISTANCE_AMD 0x883F +#define GL_PIXELS_PER_SAMPLE_PATTERN_X_AMD 0x91AE +#define GL_PIXELS_PER_SAMPLE_PATTERN_Y_AMD 0x91AF +#define GL_ALL_PIXELS_AMD 0xFFFFFFFF +typedef void (APIENTRYP PFNGLFRAMEBUFFERSAMPLEPOSITIONSFVAMDPROC) (GLenum target, GLuint numsamples, GLuint pixelindex, const GLfloat *values); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERSAMPLEPOSITIONSFVAMDPROC) (GLuint framebuffer, GLuint numsamples, GLuint pixelindex, const GLfloat *values); +typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERFVAMDPROC) (GLenum target, GLenum pname, GLuint numsamples, GLuint pixelindex, GLsizei size, GLfloat *values); +typedef void (APIENTRYP PFNGLGETNAMEDFRAMEBUFFERPARAMETERFVAMDPROC) (GLuint framebuffer, GLenum pname, GLuint numsamples, GLuint pixelindex, GLsizei size, GLfloat *values); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFramebufferSamplePositionsfvAMD (GLenum target, GLuint numsamples, GLuint pixelindex, const GLfloat *values); +GLAPI void APIENTRY glNamedFramebufferSamplePositionsfvAMD (GLuint framebuffer, GLuint numsamples, GLuint pixelindex, const GLfloat *values); +GLAPI void APIENTRY glGetFramebufferParameterfvAMD (GLenum target, GLenum pname, GLuint numsamples, GLuint pixelindex, GLsizei size, GLfloat *values); +GLAPI void APIENTRY glGetNamedFramebufferParameterfvAMD (GLuint framebuffer, GLenum pname, GLuint numsamples, GLuint pixelindex, GLsizei size, GLfloat *values); +#endif +#endif /* GL_AMD_framebuffer_sample_positions */ + #ifndef GL_AMD_gcn_shader #define GL_AMD_gcn_shader 1 #endif /* GL_AMD_gcn_shader */ +#ifndef GL_AMD_gpu_shader_half_float +#define GL_AMD_gpu_shader_half_float 1 +#define GL_FLOAT16_NV 0x8FF8 +#define GL_FLOAT16_VEC2_NV 0x8FF9 +#define GL_FLOAT16_VEC3_NV 0x8FFA +#define GL_FLOAT16_VEC4_NV 0x8FFB +#define GL_FLOAT16_MAT2_AMD 0x91C5 +#define GL_FLOAT16_MAT3_AMD 0x91C6 +#define GL_FLOAT16_MAT4_AMD 0x91C7 +#define GL_FLOAT16_MAT2x3_AMD 0x91C8 +#define GL_FLOAT16_MAT2x4_AMD 0x91C9 +#define GL_FLOAT16_MAT3x2_AMD 0x91CA +#define GL_FLOAT16_MAT3x4_AMD 0x91CB +#define GL_FLOAT16_MAT4x2_AMD 0x91CC +#define GL_FLOAT16_MAT4x3_AMD 0x91CD +#endif /* GL_AMD_gpu_shader_half_float */ + +#ifndef GL_AMD_gpu_shader_int16 +#define GL_AMD_gpu_shader_int16 1 +#endif /* GL_AMD_gpu_shader_int16 */ + #ifndef GL_AMD_gpu_shader_int64 #define GL_AMD_gpu_shader_int64 1 -typedef int64_t GLint64EXT; +typedef khronos_int64_t GLint64EXT; #define GL_INT64_NV 0x140E #define GL_UNSIGNED_INT64_NV 0x140F #define GL_INT8_NV 0x8FE0 @@ -5222,10 +5512,6 @@ typedef int64_t GLint64EXT; #define GL_UNSIGNED_INT64_VEC2_NV 0x8FF5 #define GL_UNSIGNED_INT64_VEC3_NV 0x8FF6 #define GL_UNSIGNED_INT64_VEC4_NV 0x8FF7 -#define GL_FLOAT16_NV 0x8FF8 -#define GL_FLOAT16_VEC2_NV 0x8FF9 -#define GL_FLOAT16_VEC3_NV 0x8FFA -#define GL_FLOAT16_VEC4_NV 0x8FFB typedef void (APIENTRYP PFNGLUNIFORM1I64NVPROC) (GLint location, GLint64EXT x); typedef void (APIENTRYP PFNGLUNIFORM2I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y); typedef void (APIENTRYP PFNGLUNIFORM3I64NVPROC) (GLint location, GLint64EXT x, GLint64EXT y, GLint64EXT z); @@ -5398,7 +5684,6 @@ GLAPI void APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname #ifndef GL_AMD_sample_positions #define GL_AMD_sample_positions 1 -#define GL_SUBSAMPLE_DISTANCE_AMD 0x883F typedef void (APIENTRYP PFNGLSETMULTISAMPLEFVAMDPROC) (GLenum pname, GLuint index, const GLfloat *val); #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glSetMultisamplefvAMD (GLenum pname, GLuint index, const GLfloat *val); @@ -5413,6 +5698,22 @@ GLAPI void APIENTRY glSetMultisamplefvAMD (GLenum pname, GLuint index, const GLf #define GL_AMD_shader_atomic_counter_ops 1 #endif /* GL_AMD_shader_atomic_counter_ops */ +#ifndef GL_AMD_shader_ballot +#define GL_AMD_shader_ballot 1 +#endif /* GL_AMD_shader_ballot */ + +#ifndef GL_AMD_shader_explicit_vertex_parameter +#define GL_AMD_shader_explicit_vertex_parameter 1 +#endif /* GL_AMD_shader_explicit_vertex_parameter */ + +#ifndef GL_AMD_shader_gpu_shader_half_float_fetch +#define GL_AMD_shader_gpu_shader_half_float_fetch 1 +#endif /* GL_AMD_shader_gpu_shader_half_float_fetch */ + +#ifndef GL_AMD_shader_image_load_store_lod +#define GL_AMD_shader_image_load_store_lod 1 +#endif /* GL_AMD_shader_image_load_store_lod */ + #ifndef GL_AMD_shader_stencil_export #define GL_AMD_shader_stencil_export 1 #endif /* GL_AMD_shader_stencil_export */ @@ -5452,6 +5753,10 @@ GLAPI void APIENTRY glStencilOpValueAMD (GLenum face, GLuint value); #endif #endif /* GL_AMD_stencil_operation_extended */ +#ifndef GL_AMD_texture_gather_bias_lod +#define GL_AMD_texture_gather_bias_lod 1 +#endif /* GL_AMD_texture_gather_bias_lod */ + #ifndef GL_AMD_texture_texture4 #define GL_AMD_texture_texture4 1 #endif /* GL_AMD_texture_texture4 */ @@ -6152,6 +6457,21 @@ GLAPI void APIENTRY glVertexBlendEnvfATI (GLenum pname, GLfloat param); #define GL_422_REV_AVERAGE_EXT 0x80CF #endif /* GL_EXT_422_pixels */ +#ifndef GL_EXT_EGL_image_storage +#define GL_EXT_EGL_image_storage 1 +typedef void *GLeglImageOES; +typedef void (APIENTRYP PFNGLEGLIMAGETARGETTEXSTORAGEEXTPROC) (GLenum target, GLeglImageOES image, const GLint* attrib_list); +typedef void (APIENTRYP PFNGLEGLIMAGETARGETTEXTURESTORAGEEXTPROC) (GLuint texture, GLeglImageOES image, const GLint* attrib_list); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glEGLImageTargetTexStorageEXT (GLenum target, GLeglImageOES image, const GLint* attrib_list); +GLAPI void APIENTRY glEGLImageTargetTextureStorageEXT (GLuint texture, GLeglImageOES image, const GLint* attrib_list); +#endif +#endif /* GL_EXT_EGL_image_storage */ + +#ifndef GL_EXT_EGL_sync +#define GL_EXT_EGL_sync 1 +#endif /* GL_EXT_EGL_sync */ + #ifndef GL_EXT_abgr #define GL_EXT_abgr 1 #define GL_ABGR_EXT 0x8000 @@ -6714,7 +7034,7 @@ typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC) (GLuint vaob typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC) (GLuint vaobj, GLuint attribindex, GLuint bindingindex); typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC) (GLuint vaobj, GLuint bindingindex, GLuint divisor); typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC) (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); -typedef void (APIENTRYP PFNGLTEXTUREPAGECOMMITMENTEXTPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident); +typedef void (APIENTRYP PFNGLTEXTUREPAGECOMMITMENTEXTPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit); typedef void (APIENTRYP PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC) (GLuint vaobj, GLuint index, GLuint divisor); #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glMatrixLoadfEXT (GLenum mode, const GLfloat *m); @@ -6970,7 +7290,7 @@ GLAPI void APIENTRY glVertexArrayVertexAttribLFormatEXT (GLuint vaobj, GLuint at GLAPI void APIENTRY glVertexArrayVertexAttribBindingEXT (GLuint vaobj, GLuint attribindex, GLuint bindingindex); GLAPI void APIENTRY glVertexArrayVertexBindingDivisorEXT (GLuint vaobj, GLuint bindingindex, GLuint divisor); GLAPI void APIENTRY glVertexArrayVertexAttribLOffsetEXT (GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); -GLAPI void APIENTRY glTexturePageCommitmentEXT (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean resident); +GLAPI void APIENTRY glTexturePageCommitmentEXT (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit); GLAPI void APIENTRY glVertexArrayVertexAttribDivisorEXT (GLuint vaobj, GLuint index, GLuint divisor); #endif #endif /* GL_EXT_direct_state_access */ @@ -7003,6 +7323,17 @@ GLAPI void APIENTRY glDrawRangeElementsEXT (GLenum mode, GLuint start, GLuint en #endif #endif /* GL_EXT_draw_range_elements */ +#ifndef GL_EXT_external_buffer +#define GL_EXT_external_buffer 1 +typedef void *GLeglClientBufferEXT; +typedef void (APIENTRYP PFNGLBUFFERSTORAGEEXTERNALEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags); +typedef void (APIENTRYP PFNGLNAMEDBUFFERSTORAGEEXTERNALEXTPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBufferStorageExternalEXT (GLenum target, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags); +GLAPI void APIENTRY glNamedBufferStorageExternalEXT (GLuint buffer, GLintptr offset, GLsizeiptr size, GLeglClientBufferEXT clientBuffer, GLbitfield flags); +#endif +#endif /* GL_EXT_external_buffer */ + #ifndef GL_EXT_fog_coord #define GL_EXT_fog_coord 1 #define GL_FOG_COORDINATE_SOURCE_EXT 0x8450 @@ -7039,6 +7370,16 @@ GLAPI void APIENTRY glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, #endif #endif /* GL_EXT_framebuffer_blit */ +#ifndef GL_EXT_framebuffer_blit_layers +#define GL_EXT_framebuffer_blit_layers 1 +typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERLAYERSEXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef void (APIENTRYP PFNGLBLITFRAMEBUFFERLAYEREXTPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint srcLayer, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLint dstLayer, GLbitfield mask, GLenum filter); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBlitFramebufferLayersEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +GLAPI void APIENTRY glBlitFramebufferLayerEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint srcLayer, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLint dstLayer, GLbitfield mask, GLenum filter); +#endif +#endif /* GL_EXT_framebuffer_blit_layers */ + #ifndef GL_EXT_framebuffer_multisample #define GL_EXT_framebuffer_multisample 1 #define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB @@ -7193,7 +7534,6 @@ GLAPI void APIENTRY glProgramLocalParameters4fvEXT (GLenum target, GLuint index, #ifndef GL_EXT_gpu_shader4 #define GL_EXT_gpu_shader4 1 -#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD #define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0 #define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1 #define GL_SAMPLER_BUFFER_EXT 0x8DC2 @@ -7221,6 +7561,7 @@ GLAPI void APIENTRY glProgramLocalParameters4fvEXT (GLenum target, GLuint index, #define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8 #define GL_MIN_PROGRAM_TEXEL_OFFSET_EXT 0x8904 #define GL_MAX_PROGRAM_TEXEL_OFFSET_EXT 0x8905 +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD typedef void (APIENTRYP PFNGLGETUNIFORMUIVEXTPROC) (GLuint program, GLint location, GLuint *params); typedef void (APIENTRYP PFNGLBINDFRAGDATALOCATIONEXTPROC) (GLuint program, GLuint color, const GLchar *name); typedef GLint (APIENTRYP PFNGLGETFRAGDATALOCATIONEXTPROC) (GLuint program, const GLchar *name); @@ -7232,6 +7573,29 @@ typedef void (APIENTRYP PFNGLUNIFORM1UIVEXTPROC) (GLint location, GLsizei count, typedef void (APIENTRYP PFNGLUNIFORM2UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); typedef void (APIENTRYP PFNGLUNIFORM3UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); typedef void (APIENTRYP PFNGLUNIFORM4UIVEXTPROC) (GLint location, GLsizei count, const GLuint *value); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params); #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glGetUniformuivEXT (GLuint program, GLint location, GLuint *params); GLAPI void APIENTRY glBindFragDataLocationEXT (GLuint program, GLuint color, const GLchar *name); @@ -7244,6 +7608,29 @@ GLAPI void APIENTRY glUniform1uivEXT (GLint location, GLsizei count, const GLuin GLAPI void APIENTRY glUniform2uivEXT (GLint location, GLsizei count, const GLuint *value); GLAPI void APIENTRY glUniform3uivEXT (GLint location, GLsizei count, const GLuint *value); GLAPI void APIENTRY glUniform4uivEXT (GLint location, GLsizei count, const GLuint *value); +GLAPI void APIENTRY glVertexAttribI1iEXT (GLuint index, GLint x); +GLAPI void APIENTRY glVertexAttribI2iEXT (GLuint index, GLint x, GLint y); +GLAPI void APIENTRY glVertexAttribI3iEXT (GLuint index, GLint x, GLint y, GLint z); +GLAPI void APIENTRY glVertexAttribI4iEXT (GLuint index, GLint x, GLint y, GLint z, GLint w); +GLAPI void APIENTRY glVertexAttribI1uiEXT (GLuint index, GLuint x); +GLAPI void APIENTRY glVertexAttribI2uiEXT (GLuint index, GLuint x, GLuint y); +GLAPI void APIENTRY glVertexAttribI3uiEXT (GLuint index, GLuint x, GLuint y, GLuint z); +GLAPI void APIENTRY glVertexAttribI4uiEXT (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +GLAPI void APIENTRY glVertexAttribI1ivEXT (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttribI2ivEXT (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttribI3ivEXT (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttribI4ivEXT (GLuint index, const GLint *v); +GLAPI void APIENTRY glVertexAttribI1uivEXT (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttribI2uivEXT (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttribI3uivEXT (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttribI4uivEXT (GLuint index, const GLuint *v); +GLAPI void APIENTRY glVertexAttribI4bvEXT (GLuint index, const GLbyte *v); +GLAPI void APIENTRY glVertexAttribI4svEXT (GLuint index, const GLshort *v); +GLAPI void APIENTRY glVertexAttribI4ubvEXT (GLuint index, const GLubyte *v); +GLAPI void APIENTRY glVertexAttribI4usvEXT (GLuint index, const GLushort *v); +GLAPI void APIENTRY glVertexAttribIPointerEXT (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); +GLAPI void APIENTRY glGetVertexAttribIivEXT (GLuint index, GLenum pname, GLint *params); +GLAPI void APIENTRY glGetVertexAttribIuivEXT (GLuint index, GLenum pname, GLuint *params); #endif #endif /* GL_EXT_gpu_shader4 */ @@ -7346,6 +7733,89 @@ GLAPI void APIENTRY glTextureMaterialEXT (GLenum face, GLenum mode); #endif #endif /* GL_EXT_light_texture */ +#ifndef GL_EXT_memory_object +#define GL_EXT_memory_object 1 +#define GL_TEXTURE_TILING_EXT 0x9580 +#define GL_DEDICATED_MEMORY_OBJECT_EXT 0x9581 +#define GL_PROTECTED_MEMORY_OBJECT_EXT 0x959B +#define GL_NUM_TILING_TYPES_EXT 0x9582 +#define GL_TILING_TYPES_EXT 0x9583 +#define GL_OPTIMAL_TILING_EXT 0x9584 +#define GL_LINEAR_TILING_EXT 0x9585 +#define GL_NUM_DEVICE_UUIDS_EXT 0x9596 +#define GL_DEVICE_UUID_EXT 0x9597 +#define GL_DRIVER_UUID_EXT 0x9598 +#define GL_UUID_SIZE_EXT 16 +typedef void (APIENTRYP PFNGLGETUNSIGNEDBYTEVEXTPROC) (GLenum pname, GLubyte *data); +typedef void (APIENTRYP PFNGLGETUNSIGNEDBYTEI_VEXTPROC) (GLenum target, GLuint index, GLubyte *data); +typedef void (APIENTRYP PFNGLDELETEMEMORYOBJECTSEXTPROC) (GLsizei n, const GLuint *memoryObjects); +typedef GLboolean (APIENTRYP PFNGLISMEMORYOBJECTEXTPROC) (GLuint memoryObject); +typedef void (APIENTRYP PFNGLCREATEMEMORYOBJECTSEXTPROC) (GLsizei n, GLuint *memoryObjects); +typedef void (APIENTRYP PFNGLMEMORYOBJECTPARAMETERIVEXTPROC) (GLuint memoryObject, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLGETMEMORYOBJECTPARAMETERIVEXTPROC) (GLuint memoryObject, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLTEXSTORAGEMEM2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset); +typedef void (APIENTRYP PFNGLTEXSTORAGEMEM2DMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset); +typedef void (APIENTRYP PFNGLTEXSTORAGEMEM3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset); +typedef void (APIENTRYP PFNGLTEXSTORAGEMEM3DMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset); +typedef void (APIENTRYP PFNGLBUFFERSTORAGEMEMEXTPROC) (GLenum target, GLsizeiptr size, GLuint memory, GLuint64 offset); +typedef void (APIENTRYP PFNGLTEXTURESTORAGEMEM2DEXTPROC) (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset); +typedef void (APIENTRYP PFNGLTEXTURESTORAGEMEM2DMULTISAMPLEEXTPROC) (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset); +typedef void (APIENTRYP PFNGLTEXTURESTORAGEMEM3DEXTPROC) (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset); +typedef void (APIENTRYP PFNGLTEXTURESTORAGEMEM3DMULTISAMPLEEXTPROC) (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset); +typedef void (APIENTRYP PFNGLNAMEDBUFFERSTORAGEMEMEXTPROC) (GLuint buffer, GLsizeiptr size, GLuint memory, GLuint64 offset); +typedef void (APIENTRYP PFNGLTEXSTORAGEMEM1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLuint memory, GLuint64 offset); +typedef void (APIENTRYP PFNGLTEXTURESTORAGEMEM1DEXTPROC) (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLuint memory, GLuint64 offset); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGetUnsignedBytevEXT (GLenum pname, GLubyte *data); +GLAPI void APIENTRY glGetUnsignedBytei_vEXT (GLenum target, GLuint index, GLubyte *data); +GLAPI void APIENTRY glDeleteMemoryObjectsEXT (GLsizei n, const GLuint *memoryObjects); +GLAPI GLboolean APIENTRY glIsMemoryObjectEXT (GLuint memoryObject); +GLAPI void APIENTRY glCreateMemoryObjectsEXT (GLsizei n, GLuint *memoryObjects); +GLAPI void APIENTRY glMemoryObjectParameterivEXT (GLuint memoryObject, GLenum pname, const GLint *params); +GLAPI void APIENTRY glGetMemoryObjectParameterivEXT (GLuint memoryObject, GLenum pname, GLint *params); +GLAPI void APIENTRY glTexStorageMem2DEXT (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset); +GLAPI void APIENTRY glTexStorageMem2DMultisampleEXT (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset); +GLAPI void APIENTRY glTexStorageMem3DEXT (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset); +GLAPI void APIENTRY glTexStorageMem3DMultisampleEXT (GLenum target, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset); +GLAPI void APIENTRY glBufferStorageMemEXT (GLenum target, GLsizeiptr size, GLuint memory, GLuint64 offset); +GLAPI void APIENTRY glTextureStorageMem2DEXT (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLuint memory, GLuint64 offset); +GLAPI void APIENTRY glTextureStorageMem2DMultisampleEXT (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset); +GLAPI void APIENTRY glTextureStorageMem3DEXT (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset); +GLAPI void APIENTRY glTextureStorageMem3DMultisampleEXT (GLuint texture, GLsizei samples, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedSampleLocations, GLuint memory, GLuint64 offset); +GLAPI void APIENTRY glNamedBufferStorageMemEXT (GLuint buffer, GLsizeiptr size, GLuint memory, GLuint64 offset); +GLAPI void APIENTRY glTexStorageMem1DEXT (GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLuint memory, GLuint64 offset); +GLAPI void APIENTRY glTextureStorageMem1DEXT (GLuint texture, GLsizei levels, GLenum internalFormat, GLsizei width, GLuint memory, GLuint64 offset); +#endif +#endif /* GL_EXT_memory_object */ + +#ifndef GL_EXT_memory_object_fd +#define GL_EXT_memory_object_fd 1 +#define GL_HANDLE_TYPE_OPAQUE_FD_EXT 0x9586 +typedef void (APIENTRYP PFNGLIMPORTMEMORYFDEXTPROC) (GLuint memory, GLuint64 size, GLenum handleType, GLint fd); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glImportMemoryFdEXT (GLuint memory, GLuint64 size, GLenum handleType, GLint fd); +#endif +#endif /* GL_EXT_memory_object_fd */ + +#ifndef GL_EXT_memory_object_win32 +#define GL_EXT_memory_object_win32 1 +#define GL_HANDLE_TYPE_OPAQUE_WIN32_EXT 0x9587 +#define GL_HANDLE_TYPE_OPAQUE_WIN32_KMT_EXT 0x9588 +#define GL_DEVICE_LUID_EXT 0x9599 +#define GL_DEVICE_NODE_MASK_EXT 0x959A +#define GL_LUID_SIZE_EXT 8 +#define GL_HANDLE_TYPE_D3D12_TILEPOOL_EXT 0x9589 +#define GL_HANDLE_TYPE_D3D12_RESOURCE_EXT 0x958A +#define GL_HANDLE_TYPE_D3D11_IMAGE_EXT 0x958B +#define GL_HANDLE_TYPE_D3D11_IMAGE_KMT_EXT 0x958C +typedef void (APIENTRYP PFNGLIMPORTMEMORYWIN32HANDLEEXTPROC) (GLuint memory, GLuint64 size, GLenum handleType, void *handle); +typedef void (APIENTRYP PFNGLIMPORTMEMORYWIN32NAMEEXTPROC) (GLuint memory, GLuint64 size, GLenum handleType, const void *name); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glImportMemoryWin32HandleEXT (GLuint memory, GLuint64 size, GLenum handleType, void *handle); +GLAPI void APIENTRY glImportMemoryWin32NameEXT (GLuint memory, GLuint64 size, GLenum handleType, const void *name); +#endif +#endif /* GL_EXT_memory_object_win32 */ + #ifndef GL_EXT_misc_attribute #define GL_EXT_misc_attribute 1 #endif /* GL_EXT_misc_attribute */ @@ -7387,6 +7857,18 @@ GLAPI void APIENTRY glSamplePatternEXT (GLenum pattern); #endif #endif /* GL_EXT_multisample */ +#ifndef GL_EXT_multiview_tessellation_geometry_shader +#define GL_EXT_multiview_tessellation_geometry_shader 1 +#endif /* GL_EXT_multiview_tessellation_geometry_shader */ + +#ifndef GL_EXT_multiview_texture_multisample +#define GL_EXT_multiview_texture_multisample 1 +#endif /* GL_EXT_multiview_texture_multisample */ + +#ifndef GL_EXT_multiview_timer_query +#define GL_EXT_multiview_timer_query 1 +#endif /* GL_EXT_multiview_timer_query */ + #ifndef GL_EXT_packed_depth_stencil #define GL_EXT_packed_depth_stencil 1 #define GL_DEPTH_STENCIL_EXT 0x84F9 @@ -7587,6 +8069,55 @@ GLAPI void APIENTRY glSecondaryColorPointerEXT (GLint size, GLenum type, GLsizei #endif #endif /* GL_EXT_secondary_color */ +#ifndef GL_EXT_semaphore +#define GL_EXT_semaphore 1 +#define GL_LAYOUT_GENERAL_EXT 0x958D +#define GL_LAYOUT_COLOR_ATTACHMENT_EXT 0x958E +#define GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT 0x958F +#define GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT 0x9590 +#define GL_LAYOUT_SHADER_READ_ONLY_EXT 0x9591 +#define GL_LAYOUT_TRANSFER_SRC_EXT 0x9592 +#define GL_LAYOUT_TRANSFER_DST_EXT 0x9593 +#define GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT 0x9530 +#define GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT 0x9531 +typedef void (APIENTRYP PFNGLGENSEMAPHORESEXTPROC) (GLsizei n, GLuint *semaphores); +typedef void (APIENTRYP PFNGLDELETESEMAPHORESEXTPROC) (GLsizei n, const GLuint *semaphores); +typedef GLboolean (APIENTRYP PFNGLISSEMAPHOREEXTPROC) (GLuint semaphore); +typedef void (APIENTRYP PFNGLSEMAPHOREPARAMETERUI64VEXTPROC) (GLuint semaphore, GLenum pname, const GLuint64 *params); +typedef void (APIENTRYP PFNGLGETSEMAPHOREPARAMETERUI64VEXTPROC) (GLuint semaphore, GLenum pname, GLuint64 *params); +typedef void (APIENTRYP PFNGLWAITSEMAPHOREEXTPROC) (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *srcLayouts); +typedef void (APIENTRYP PFNGLSIGNALSEMAPHOREEXTPROC) (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *dstLayouts); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGenSemaphoresEXT (GLsizei n, GLuint *semaphores); +GLAPI void APIENTRY glDeleteSemaphoresEXT (GLsizei n, const GLuint *semaphores); +GLAPI GLboolean APIENTRY glIsSemaphoreEXT (GLuint semaphore); +GLAPI void APIENTRY glSemaphoreParameterui64vEXT (GLuint semaphore, GLenum pname, const GLuint64 *params); +GLAPI void APIENTRY glGetSemaphoreParameterui64vEXT (GLuint semaphore, GLenum pname, GLuint64 *params); +GLAPI void APIENTRY glWaitSemaphoreEXT (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *srcLayouts); +GLAPI void APIENTRY glSignalSemaphoreEXT (GLuint semaphore, GLuint numBufferBarriers, const GLuint *buffers, GLuint numTextureBarriers, const GLuint *textures, const GLenum *dstLayouts); +#endif +#endif /* GL_EXT_semaphore */ + +#ifndef GL_EXT_semaphore_fd +#define GL_EXT_semaphore_fd 1 +typedef void (APIENTRYP PFNGLIMPORTSEMAPHOREFDEXTPROC) (GLuint semaphore, GLenum handleType, GLint fd); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glImportSemaphoreFdEXT (GLuint semaphore, GLenum handleType, GLint fd); +#endif +#endif /* GL_EXT_semaphore_fd */ + +#ifndef GL_EXT_semaphore_win32 +#define GL_EXT_semaphore_win32 1 +#define GL_HANDLE_TYPE_D3D12_FENCE_EXT 0x9594 +#define GL_D3D12_FENCE_VALUE_EXT 0x9595 +typedef void (APIENTRYP PFNGLIMPORTSEMAPHOREWIN32HANDLEEXTPROC) (GLuint semaphore, GLenum handleType, void *handle); +typedef void (APIENTRYP PFNGLIMPORTSEMAPHOREWIN32NAMEEXTPROC) (GLuint semaphore, GLenum handleType, const void *name); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glImportSemaphoreWin32HandleEXT (GLuint semaphore, GLenum handleType, void *handle); +GLAPI void APIENTRY glImportSemaphoreWin32NameEXT (GLuint semaphore, GLenum handleType, const void *name); +#endif +#endif /* GL_EXT_semaphore_win32 */ + #ifndef GL_EXT_separate_shader_objects #define GL_EXT_separate_shader_objects 1 #define GL_ACTIVE_PROGRAM_EXT 0x8B8D @@ -7607,6 +8138,19 @@ GLAPI GLuint APIENTRY glCreateShaderProgramEXT (GLenum type, const GLchar *strin #define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA #endif /* GL_EXT_separate_specular_color */ +#ifndef GL_EXT_shader_framebuffer_fetch +#define GL_EXT_shader_framebuffer_fetch 1 +#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52 +#endif /* GL_EXT_shader_framebuffer_fetch */ + +#ifndef GL_EXT_shader_framebuffer_fetch_non_coherent +#define GL_EXT_shader_framebuffer_fetch_non_coherent 1 +typedef void (APIENTRYP PFNGLFRAMEBUFFERFETCHBARRIEREXTPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFramebufferFetchBarrierEXT (void); +#endif +#endif /* GL_EXT_shader_framebuffer_fetch_non_coherent */ + #ifndef GL_EXT_shader_image_load_formatted #define GL_EXT_shader_image_load_formatted 1 #endif /* GL_EXT_shader_image_load_formatted */ @@ -7680,6 +8224,10 @@ GLAPI void APIENTRY glMemoryBarrierEXT (GLbitfield barriers); #define GL_EXT_shader_integer_mix 1 #endif /* GL_EXT_shader_integer_mix */ +#ifndef GL_EXT_shader_samples_identical +#define GL_EXT_shader_samples_identical 1 +#endif /* GL_EXT_shader_samples_identical */ + #ifndef GL_EXT_shadow_funcs #define GL_EXT_shadow_funcs 1 #endif /* GL_EXT_shadow_funcs */ @@ -7907,6 +8455,8 @@ GLAPI void APIENTRY glTexBufferEXT (GLenum target, GLenum internalformat, GLuint #ifndef GL_EXT_texture_filter_minmax #define GL_EXT_texture_filter_minmax 1 +#define GL_TEXTURE_REDUCTION_MODE_EXT 0x9366 +#define GL_WEIGHTED_AVERAGE_EXT 0x9367 #endif /* GL_EXT_texture_filter_minmax */ #ifndef GL_EXT_texture_integer @@ -8041,6 +8591,16 @@ GLAPI void APIENTRY glTextureNormalEXT (GLenum mode); #define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F #endif /* GL_EXT_texture_sRGB */ +#ifndef GL_EXT_texture_sRGB_R8 +#define GL_EXT_texture_sRGB_R8 1 +#define GL_SR8_EXT 0x8FBD +#endif /* GL_EXT_texture_sRGB_R8 */ + +#ifndef GL_EXT_texture_sRGB_RG8 +#define GL_EXT_texture_sRGB_RG8 1 +#define GL_SRG8_EXT 0x8FBE +#endif /* GL_EXT_texture_sRGB_RG8 */ + #ifndef GL_EXT_texture_sRGB_decode #define GL_EXT_texture_sRGB_decode 1 #define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48 @@ -8048,6 +8608,10 @@ GLAPI void APIENTRY glTextureNormalEXT (GLenum mode); #define GL_SKIP_DECODE_EXT 0x8A4A #endif /* GL_EXT_texture_sRGB_decode */ +#ifndef GL_EXT_texture_shadow_lod +#define GL_EXT_texture_shadow_lod 1 +#endif /* GL_EXT_texture_shadow_lod */ + #ifndef GL_EXT_texture_shared_exponent #define GL_EXT_texture_shared_exponent 1 #define GL_RGB9_E5_EXT 0x8C3D @@ -8075,6 +8639,36 @@ GLAPI void APIENTRY glTextureNormalEXT (GLenum mode); #define GL_RGBA_SNORM 0x8F93 #endif /* GL_EXT_texture_snorm */ +#ifndef GL_EXT_texture_storage +#define GL_EXT_texture_storage 1 +#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F +#define GL_RGBA32F_EXT 0x8814 +#define GL_RGB32F_EXT 0x8815 +#define GL_ALPHA32F_EXT 0x8816 +#define GL_LUMINANCE32F_EXT 0x8818 +#define GL_LUMINANCE_ALPHA32F_EXT 0x8819 +#define GL_RGBA16F_EXT 0x881A +#define GL_RGB16F_EXT 0x881B +#define GL_ALPHA16F_EXT 0x881C +#define GL_LUMINANCE16F_EXT 0x881E +#define GL_LUMINANCE_ALPHA16F_EXT 0x881F +#define GL_BGRA8_EXT 0x93A1 +#define GL_R8_EXT 0x8229 +#define GL_RG8_EXT 0x822B +#define GL_R32F_EXT 0x822E +#define GL_RG32F_EXT 0x8230 +#define GL_R16F_EXT 0x822D +#define GL_RG16F_EXT 0x822F +typedef void (APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glTexStorage1DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +GLAPI void APIENTRY glTexStorage2DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI void APIENTRY glTexStorage3DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +#endif +#endif /* GL_EXT_texture_storage */ + #ifndef GL_EXT_texture_swizzle #define GL_EXT_texture_swizzle 1 #define GL_TEXTURE_SWIZZLE_R_EXT 0x8E42 @@ -8453,6 +9047,30 @@ GLAPI void APIENTRY glVertexWeightPointerEXT (GLint size, GLenum type, GLsizei s #endif #endif /* GL_EXT_vertex_weighting */ +#ifndef GL_EXT_win32_keyed_mutex +#define GL_EXT_win32_keyed_mutex 1 +typedef GLboolean (APIENTRYP PFNGLACQUIREKEYEDMUTEXWIN32EXTPROC) (GLuint memory, GLuint64 key, GLuint timeout); +typedef GLboolean (APIENTRYP PFNGLRELEASEKEYEDMUTEXWIN32EXTPROC) (GLuint memory, GLuint64 key); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLboolean APIENTRY glAcquireKeyedMutexWin32EXT (GLuint memory, GLuint64 key, GLuint timeout); +GLAPI GLboolean APIENTRY glReleaseKeyedMutexWin32EXT (GLuint memory, GLuint64 key); +#endif +#endif /* GL_EXT_win32_keyed_mutex */ + +#ifndef GL_EXT_window_rectangles +#define GL_EXT_window_rectangles 1 +#define GL_INCLUSIVE_EXT 0x8F10 +#define GL_EXCLUSIVE_EXT 0x8F11 +#define GL_WINDOW_RECTANGLE_EXT 0x8F12 +#define GL_WINDOW_RECTANGLE_MODE_EXT 0x8F13 +#define GL_MAX_WINDOW_RECTANGLES_EXT 0x8F14 +#define GL_NUM_WINDOW_RECTANGLES_EXT 0x8F15 +typedef void (APIENTRYP PFNGLWINDOWRECTANGLESEXTPROC) (GLenum mode, GLsizei count, const GLint *box); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glWindowRectanglesEXT (GLenum mode, GLsizei count, const GLint *box); +#endif +#endif /* GL_EXT_window_rectangles */ + #ifndef GL_EXT_x11_sync_object #define GL_EXT_x11_sync_object 1 #define GL_SYNC_X11_FENCE_EXT 0x90E1 @@ -8630,10 +9248,28 @@ GLAPI void APIENTRY glBlendFuncSeparateINGR (GLenum sfactorRGB, GLenum dfactorRG #define GL_INTERLACE_READ_INGR 0x8568 #endif /* GL_INGR_interlace_read */ +#ifndef GL_INTEL_blackhole_render +#define GL_INTEL_blackhole_render 1 +#define GL_BLACKHOLE_RENDER_INTEL 0x83FC +#endif /* GL_INTEL_blackhole_render */ + +#ifndef GL_INTEL_conservative_rasterization +#define GL_INTEL_conservative_rasterization 1 +#define GL_CONSERVATIVE_RASTERIZATION_INTEL 0x83FE +#endif /* GL_INTEL_conservative_rasterization */ + #ifndef GL_INTEL_fragment_shader_ordering #define GL_INTEL_fragment_shader_ordering 1 #endif /* GL_INTEL_fragment_shader_ordering */ +#ifndef GL_INTEL_framebuffer_CMAA +#define GL_INTEL_framebuffer_CMAA 1 +typedef void (APIENTRYP PFNGLAPPLYFRAMEBUFFERATTACHMENTCMAAINTELPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glApplyFramebufferAttachmentCMAAINTEL (void); +#endif +#endif /* GL_INTEL_framebuffer_CMAA */ + #ifndef GL_INTEL_map_texture #define GL_INTEL_map_texture 1 #define GL_TEXTURE_MEMORY_LAYOUT_INTEL 0x83FF @@ -8698,7 +9334,7 @@ typedef void (APIENTRYP PFNGLENDPERFQUERYINTELPROC) (GLuint queryHandle); typedef void (APIENTRYP PFNGLGETFIRSTPERFQUERYIDINTELPROC) (GLuint *queryId); typedef void (APIENTRYP PFNGLGETNEXTPERFQUERYIDINTELPROC) (GLuint queryId, GLuint *nextQueryId); typedef void (APIENTRYP PFNGLGETPERFCOUNTERINFOINTELPROC) (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue); -typedef void (APIENTRYP PFNGLGETPERFQUERYDATAINTELPROC) (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten); +typedef void (APIENTRYP PFNGLGETPERFQUERYDATAINTELPROC) (GLuint queryHandle, GLuint flags, GLsizei dataSize, void *data, GLuint *bytesWritten); typedef void (APIENTRYP PFNGLGETPERFQUERYIDBYNAMEINTELPROC) (GLchar *queryName, GLuint *queryId); typedef void (APIENTRYP PFNGLGETPERFQUERYINFOINTELPROC) (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask); #ifdef GL_GLEXT_PROTOTYPES @@ -8709,7 +9345,7 @@ GLAPI void APIENTRY glEndPerfQueryINTEL (GLuint queryHandle); GLAPI void APIENTRY glGetFirstPerfQueryIdINTEL (GLuint *queryId); GLAPI void APIENTRY glGetNextPerfQueryIdINTEL (GLuint queryId, GLuint *nextQueryId); GLAPI void APIENTRY glGetPerfCounterInfoINTEL (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue); -GLAPI void APIENTRY glGetPerfQueryDataINTEL (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten); +GLAPI void APIENTRY glGetPerfQueryDataINTEL (GLuint queryHandle, GLuint flags, GLsizei dataSize, void *data, GLuint *bytesWritten); GLAPI void APIENTRY glGetPerfQueryIdByNameINTEL (GLchar *queryName, GLuint *queryId); GLAPI void APIENTRY glGetPerfQueryInfoINTEL (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask); #endif @@ -8725,11 +9361,37 @@ GLAPI void APIENTRY glGetPerfQueryInfoINTEL (GLuint queryId, GLuint queryNameLen #define GL_TEXTURE_2D_STACK_BINDING_MESAX 0x875E #endif /* GL_MESAX_texture_stack */ +#ifndef GL_MESA_framebuffer_flip_x +#define GL_MESA_framebuffer_flip_x 1 +#define GL_FRAMEBUFFER_FLIP_X_MESA 0x8BBC +#endif /* GL_MESA_framebuffer_flip_x */ + +#ifndef GL_MESA_framebuffer_flip_y +#define GL_MESA_framebuffer_flip_y 1 +#define GL_FRAMEBUFFER_FLIP_Y_MESA 0x8BBB +typedef void (APIENTRYP PFNGLFRAMEBUFFERPARAMETERIMESAPROC) (GLenum target, GLenum pname, GLint param); +typedef void (APIENTRYP PFNGLGETFRAMEBUFFERPARAMETERIVMESAPROC) (GLenum target, GLenum pname, GLint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFramebufferParameteriMESA (GLenum target, GLenum pname, GLint param); +GLAPI void APIENTRY glGetFramebufferParameterivMESA (GLenum target, GLenum pname, GLint *params); +#endif +#endif /* GL_MESA_framebuffer_flip_y */ + +#ifndef GL_MESA_framebuffer_swap_xy +#define GL_MESA_framebuffer_swap_xy 1 +#define GL_FRAMEBUFFER_SWAP_XY_MESA 0x8BBD +#endif /* GL_MESA_framebuffer_swap_xy */ + #ifndef GL_MESA_pack_invert #define GL_MESA_pack_invert 1 #define GL_PACK_INVERT_MESA 0x8758 #endif /* GL_MESA_pack_invert */ +#ifndef GL_MESA_program_binary_formats +#define GL_MESA_program_binary_formats 1 +#define GL_PROGRAM_BINARY_FORMAT_MESA 0x875F +#endif /* GL_MESA_program_binary_formats */ + #ifndef GL_MESA_resize_buffers #define GL_MESA_resize_buffers 1 typedef void (APIENTRYP PFNGLRESIZEBUFFERSMESAPROC) (void); @@ -8738,6 +9400,17 @@ GLAPI void APIENTRY glResizeBuffersMESA (void); #endif #endif /* GL_MESA_resize_buffers */ +#ifndef GL_MESA_shader_integer_functions +#define GL_MESA_shader_integer_functions 1 +#endif /* GL_MESA_shader_integer_functions */ + +#ifndef GL_MESA_tile_raster_order +#define GL_MESA_tile_raster_order 1 +#define GL_TILE_RASTER_ORDER_FIXED_MESA 0x8BB8 +#define GL_TILE_RASTER_ORDER_INCREASING_X_MESA 0x8BB9 +#define GL_TILE_RASTER_ORDER_INCREASING_Y_MESA 0x8BBA +#endif /* GL_MESA_tile_raster_order */ + #ifndef GL_MESA_window_pos #define GL_MESA_window_pos 1 typedef void (APIENTRYP PFNGLWINDOWPOS2DMESAPROC) (GLdouble x, GLdouble y); @@ -8799,6 +9472,10 @@ GLAPI void APIENTRY glWindowPos4svMESA (const GLshort *v); #define GL_YCBCR_MESA 0x8757 #endif /* GL_MESA_ycbcr_texture */ +#ifndef GL_NVX_blend_equation_advanced_multi_draw_buffers +#define GL_NVX_blend_equation_advanced_multi_draw_buffers 1 +#endif /* GL_NVX_blend_equation_advanced_multi_draw_buffers */ + #ifndef GL_NVX_conditional_render #define GL_NVX_conditional_render 1 typedef void (APIENTRYP PFNGLBEGINCONDITIONALRENDERNVXPROC) (GLuint id); @@ -8818,6 +9495,65 @@ GLAPI void APIENTRY glEndConditionalRenderNVX (void); #define GL_GPU_MEMORY_INFO_EVICTED_MEMORY_NVX 0x904B #endif /* GL_NVX_gpu_memory_info */ +#ifndef GL_NVX_gpu_multicast2 +#define GL_NVX_gpu_multicast2 1 +#define GL_UPLOAD_GPU_MASK_NVX 0x954A +typedef void (APIENTRYP PFNGLUPLOADGPUMASKNVXPROC) (GLbitfield mask); +typedef void (APIENTRYP PFNGLMULTICASTVIEWPORTARRAYVNVXPROC) (GLuint gpu, GLuint first, GLsizei count, const GLfloat *v); +typedef void (APIENTRYP PFNGLMULTICASTVIEWPORTPOSITIONWSCALENVXPROC) (GLuint gpu, GLuint index, GLfloat xcoeff, GLfloat ycoeff); +typedef void (APIENTRYP PFNGLMULTICASTSCISSORARRAYVNVXPROC) (GLuint gpu, GLuint first, GLsizei count, const GLint *v); +typedef GLuint (APIENTRYP PFNGLASYNCCOPYBUFFERSUBDATANVXPROC) (GLsizei waitSemaphoreCount, const GLuint *waitSemaphoreArray, const GLuint64 *fenceValueArray, GLuint readGpu, GLbitfield writeGpuMask, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size, GLsizei signalSemaphoreCount, const GLuint *signalSemaphoreArray, const GLuint64 *signalValueArray); +typedef GLuint (APIENTRYP PFNGLASYNCCOPYIMAGESUBDATANVXPROC) (GLsizei waitSemaphoreCount, const GLuint *waitSemaphoreArray, const GLuint64 *waitValueArray, GLuint srcGpu, GLbitfield dstGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth, GLsizei signalSemaphoreCount, const GLuint *signalSemaphoreArray, const GLuint64 *signalValueArray); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glUploadGpuMaskNVX (GLbitfield mask); +GLAPI void APIENTRY glMulticastViewportArrayvNVX (GLuint gpu, GLuint first, GLsizei count, const GLfloat *v); +GLAPI void APIENTRY glMulticastViewportPositionWScaleNVX (GLuint gpu, GLuint index, GLfloat xcoeff, GLfloat ycoeff); +GLAPI void APIENTRY glMulticastScissorArrayvNVX (GLuint gpu, GLuint first, GLsizei count, const GLint *v); +GLAPI GLuint APIENTRY glAsyncCopyBufferSubDataNVX (GLsizei waitSemaphoreCount, const GLuint *waitSemaphoreArray, const GLuint64 *fenceValueArray, GLuint readGpu, GLbitfield writeGpuMask, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size, GLsizei signalSemaphoreCount, const GLuint *signalSemaphoreArray, const GLuint64 *signalValueArray); +GLAPI GLuint APIENTRY glAsyncCopyImageSubDataNVX (GLsizei waitSemaphoreCount, const GLuint *waitSemaphoreArray, const GLuint64 *waitValueArray, GLuint srcGpu, GLbitfield dstGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth, GLsizei signalSemaphoreCount, const GLuint *signalSemaphoreArray, const GLuint64 *signalValueArray); +#endif +#endif /* GL_NVX_gpu_multicast2 */ + +#ifndef GL_NVX_linked_gpu_multicast +#define GL_NVX_linked_gpu_multicast 1 +#define GL_LGPU_SEPARATE_STORAGE_BIT_NVX 0x0800 +#define GL_MAX_LGPU_GPUS_NVX 0x92BA +typedef void (APIENTRYP PFNGLLGPUNAMEDBUFFERSUBDATANVXPROC) (GLbitfield gpuMask, GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data); +typedef void (APIENTRYP PFNGLLGPUCOPYIMAGESUBDATANVXPROC) (GLuint sourceGpu, GLbitfield destinationGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srxY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); +typedef void (APIENTRYP PFNGLLGPUINTERLOCKNVXPROC) (void); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glLGPUNamedBufferSubDataNVX (GLbitfield gpuMask, GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data); +GLAPI void APIENTRY glLGPUCopyImageSubDataNVX (GLuint sourceGpu, GLbitfield destinationGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srxY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei width, GLsizei height, GLsizei depth); +GLAPI void APIENTRY glLGPUInterlockNVX (void); +#endif +#endif /* GL_NVX_linked_gpu_multicast */ + +#ifndef GL_NVX_progress_fence +#define GL_NVX_progress_fence 1 +typedef GLuint (APIENTRYP PFNGLCREATEPROGRESSFENCENVXPROC) (void); +typedef void (APIENTRYP PFNGLSIGNALSEMAPHOREUI64NVXPROC) (GLuint signalGpu, GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray); +typedef void (APIENTRYP PFNGLWAITSEMAPHOREUI64NVXPROC) (GLuint waitGpu, GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray); +typedef void (APIENTRYP PFNGLCLIENTWAITSEMAPHOREUI64NVXPROC) (GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLuint APIENTRY glCreateProgressFenceNVX (void); +GLAPI void APIENTRY glSignalSemaphoreui64NVX (GLuint signalGpu, GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray); +GLAPI void APIENTRY glWaitSemaphoreui64NVX (GLuint waitGpu, GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray); +GLAPI void APIENTRY glClientWaitSemaphoreui64NVX (GLsizei fenceObjectCount, const GLuint *semaphoreArray, const GLuint64 *fenceValueArray); +#endif +#endif /* GL_NVX_progress_fence */ + +#ifndef GL_NV_alpha_to_coverage_dither_control +#define GL_NV_alpha_to_coverage_dither_control 1 +#define GL_ALPHA_TO_COVERAGE_DITHER_DEFAULT_NV 0x934D +#define GL_ALPHA_TO_COVERAGE_DITHER_ENABLE_NV 0x934E +#define GL_ALPHA_TO_COVERAGE_DITHER_DISABLE_NV 0x934F +#define GL_ALPHA_TO_COVERAGE_DITHER_MODE_NV 0x92BF +typedef void (APIENTRYP PFNGLALPHATOCOVERAGEDITHERCONTROLNVPROC) (GLenum mode); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glAlphaToCoverageDitherControlNV (GLenum mode); +#endif +#endif /* GL_NV_alpha_to_coverage_dither_control */ + #ifndef GL_NV_bindless_multi_draw_indirect #define GL_NV_bindless_multi_draw_indirect 1 typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTBINDLESSNVPROC) (GLenum mode, const void *indirect, GLsizei drawCount, GLsizei stride, GLint vertexBufferCount); @@ -8934,16 +9670,94 @@ GLAPI void APIENTRY glBlendBarrierNV (void); #define GL_BLEND_ADVANCED_COHERENT_NV 0x9285 #endif /* GL_NV_blend_equation_advanced_coherent */ +#ifndef GL_NV_blend_minmax_factor +#define GL_NV_blend_minmax_factor 1 +#endif /* GL_NV_blend_minmax_factor */ + #ifndef GL_NV_blend_square #define GL_NV_blend_square 1 #endif /* GL_NV_blend_square */ +#ifndef GL_NV_clip_space_w_scaling +#define GL_NV_clip_space_w_scaling 1 +#define GL_VIEWPORT_POSITION_W_SCALE_NV 0x937C +#define GL_VIEWPORT_POSITION_W_SCALE_X_COEFF_NV 0x937D +#define GL_VIEWPORT_POSITION_W_SCALE_Y_COEFF_NV 0x937E +typedef void (APIENTRYP PFNGLVIEWPORTPOSITIONWSCALENVPROC) (GLuint index, GLfloat xcoeff, GLfloat ycoeff); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glViewportPositionWScaleNV (GLuint index, GLfloat xcoeff, GLfloat ycoeff); +#endif +#endif /* GL_NV_clip_space_w_scaling */ + +#ifndef GL_NV_command_list +#define GL_NV_command_list 1 +#define GL_TERMINATE_SEQUENCE_COMMAND_NV 0x0000 +#define GL_NOP_COMMAND_NV 0x0001 +#define GL_DRAW_ELEMENTS_COMMAND_NV 0x0002 +#define GL_DRAW_ARRAYS_COMMAND_NV 0x0003 +#define GL_DRAW_ELEMENTS_STRIP_COMMAND_NV 0x0004 +#define GL_DRAW_ARRAYS_STRIP_COMMAND_NV 0x0005 +#define GL_DRAW_ELEMENTS_INSTANCED_COMMAND_NV 0x0006 +#define GL_DRAW_ARRAYS_INSTANCED_COMMAND_NV 0x0007 +#define GL_ELEMENT_ADDRESS_COMMAND_NV 0x0008 +#define GL_ATTRIBUTE_ADDRESS_COMMAND_NV 0x0009 +#define GL_UNIFORM_ADDRESS_COMMAND_NV 0x000A +#define GL_BLEND_COLOR_COMMAND_NV 0x000B +#define GL_STENCIL_REF_COMMAND_NV 0x000C +#define GL_LINE_WIDTH_COMMAND_NV 0x000D +#define GL_POLYGON_OFFSET_COMMAND_NV 0x000E +#define GL_ALPHA_REF_COMMAND_NV 0x000F +#define GL_VIEWPORT_COMMAND_NV 0x0010 +#define GL_SCISSOR_COMMAND_NV 0x0011 +#define GL_FRONT_FACE_COMMAND_NV 0x0012 +typedef void (APIENTRYP PFNGLCREATESTATESNVPROC) (GLsizei n, GLuint *states); +typedef void (APIENTRYP PFNGLDELETESTATESNVPROC) (GLsizei n, const GLuint *states); +typedef GLboolean (APIENTRYP PFNGLISSTATENVPROC) (GLuint state); +typedef void (APIENTRYP PFNGLSTATECAPTURENVPROC) (GLuint state, GLenum mode); +typedef GLuint (APIENTRYP PFNGLGETCOMMANDHEADERNVPROC) (GLenum tokenID, GLuint size); +typedef GLushort (APIENTRYP PFNGLGETSTAGEINDEXNVPROC) (GLenum shadertype); +typedef void (APIENTRYP PFNGLDRAWCOMMANDSNVPROC) (GLenum primitiveMode, GLuint buffer, const GLintptr *indirects, const GLsizei *sizes, GLuint count); +typedef void (APIENTRYP PFNGLDRAWCOMMANDSADDRESSNVPROC) (GLenum primitiveMode, const GLuint64 *indirects, const GLsizei *sizes, GLuint count); +typedef void (APIENTRYP PFNGLDRAWCOMMANDSSTATESNVPROC) (GLuint buffer, const GLintptr *indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count); +typedef void (APIENTRYP PFNGLDRAWCOMMANDSSTATESADDRESSNVPROC) (const GLuint64 *indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count); +typedef void (APIENTRYP PFNGLCREATECOMMANDLISTSNVPROC) (GLsizei n, GLuint *lists); +typedef void (APIENTRYP PFNGLDELETECOMMANDLISTSNVPROC) (GLsizei n, const GLuint *lists); +typedef GLboolean (APIENTRYP PFNGLISCOMMANDLISTNVPROC) (GLuint list); +typedef void (APIENTRYP PFNGLLISTDRAWCOMMANDSSTATESCLIENTNVPROC) (GLuint list, GLuint segment, const void **indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count); +typedef void (APIENTRYP PFNGLCOMMANDLISTSEGMENTSNVPROC) (GLuint list, GLuint segments); +typedef void (APIENTRYP PFNGLCOMPILECOMMANDLISTNVPROC) (GLuint list); +typedef void (APIENTRYP PFNGLCALLCOMMANDLISTNVPROC) (GLuint list); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glCreateStatesNV (GLsizei n, GLuint *states); +GLAPI void APIENTRY glDeleteStatesNV (GLsizei n, const GLuint *states); +GLAPI GLboolean APIENTRY glIsStateNV (GLuint state); +GLAPI void APIENTRY glStateCaptureNV (GLuint state, GLenum mode); +GLAPI GLuint APIENTRY glGetCommandHeaderNV (GLenum tokenID, GLuint size); +GLAPI GLushort APIENTRY glGetStageIndexNV (GLenum shadertype); +GLAPI void APIENTRY glDrawCommandsNV (GLenum primitiveMode, GLuint buffer, const GLintptr *indirects, const GLsizei *sizes, GLuint count); +GLAPI void APIENTRY glDrawCommandsAddressNV (GLenum primitiveMode, const GLuint64 *indirects, const GLsizei *sizes, GLuint count); +GLAPI void APIENTRY glDrawCommandsStatesNV (GLuint buffer, const GLintptr *indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count); +GLAPI void APIENTRY glDrawCommandsStatesAddressNV (const GLuint64 *indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count); +GLAPI void APIENTRY glCreateCommandListsNV (GLsizei n, GLuint *lists); +GLAPI void APIENTRY glDeleteCommandListsNV (GLsizei n, const GLuint *lists); +GLAPI GLboolean APIENTRY glIsCommandListNV (GLuint list); +GLAPI void APIENTRY glListDrawCommandsStatesClientNV (GLuint list, GLuint segment, const void **indirects, const GLsizei *sizes, const GLuint *states, const GLuint *fbos, GLuint count); +GLAPI void APIENTRY glCommandListSegmentsNV (GLuint list, GLuint segments); +GLAPI void APIENTRY glCompileCommandListNV (GLuint list); +GLAPI void APIENTRY glCallCommandListNV (GLuint list); +#endif +#endif /* GL_NV_command_list */ + #ifndef GL_NV_compute_program5 #define GL_NV_compute_program5 1 #define GL_COMPUTE_PROGRAM_NV 0x90FB #define GL_COMPUTE_PROGRAM_PARAMETER_BUFFER_NV 0x90FC #endif /* GL_NV_compute_program5 */ +#ifndef GL_NV_compute_shader_derivatives +#define GL_NV_compute_shader_derivatives 1 +#endif /* GL_NV_compute_shader_derivatives */ + #ifndef GL_NV_conditional_render #define GL_NV_conditional_render 1 #define GL_QUERY_WAIT_NV 0x8E13 @@ -8970,6 +9784,37 @@ GLAPI void APIENTRY glSubpixelPrecisionBiasNV (GLuint xbits, GLuint ybits); #endif #endif /* GL_NV_conservative_raster */ +#ifndef GL_NV_conservative_raster_dilate +#define GL_NV_conservative_raster_dilate 1 +#define GL_CONSERVATIVE_RASTER_DILATE_NV 0x9379 +#define GL_CONSERVATIVE_RASTER_DILATE_RANGE_NV 0x937A +#define GL_CONSERVATIVE_RASTER_DILATE_GRANULARITY_NV 0x937B +typedef void (APIENTRYP PFNGLCONSERVATIVERASTERPARAMETERFNVPROC) (GLenum pname, GLfloat value); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glConservativeRasterParameterfNV (GLenum pname, GLfloat value); +#endif +#endif /* GL_NV_conservative_raster_dilate */ + +#ifndef GL_NV_conservative_raster_pre_snap +#define GL_NV_conservative_raster_pre_snap 1 +#define GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_NV 0x9550 +#endif /* GL_NV_conservative_raster_pre_snap */ + +#ifndef GL_NV_conservative_raster_pre_snap_triangles +#define GL_NV_conservative_raster_pre_snap_triangles 1 +#define GL_CONSERVATIVE_RASTER_MODE_NV 0x954D +#define GL_CONSERVATIVE_RASTER_MODE_POST_SNAP_NV 0x954E +#define GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_TRIANGLES_NV 0x954F +typedef void (APIENTRYP PFNGLCONSERVATIVERASTERPARAMETERINVPROC) (GLenum pname, GLint param); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glConservativeRasterParameteriNV (GLenum pname, GLint param); +#endif +#endif /* GL_NV_conservative_raster_pre_snap_triangles */ + +#ifndef GL_NV_conservative_raster_underestimation +#define GL_NV_conservative_raster_underestimation 1 +#endif /* GL_NV_conservative_raster_underestimation */ + #ifndef GL_NV_copy_depth_to_color #define GL_NV_copy_depth_to_color 1 #define GL_DEPTH_STENCIL_TO_RGBA_NV 0x886E @@ -9019,6 +9864,23 @@ GLAPI void APIENTRY glDrawTextureNV (GLuint texture, GLuint sampler, GLfloat x0, #endif #endif /* GL_NV_draw_texture */ +#ifndef GL_NV_draw_vulkan_image +#define GL_NV_draw_vulkan_image 1 +typedef void (APIENTRY *GLVULKANPROCNV)(void); +typedef void (APIENTRYP PFNGLDRAWVKIMAGENVPROC) (GLuint64 vkImage, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1); +typedef GLVULKANPROCNV (APIENTRYP PFNGLGETVKPROCADDRNVPROC) (const GLchar *name); +typedef void (APIENTRYP PFNGLWAITVKSEMAPHORENVPROC) (GLuint64 vkSemaphore); +typedef void (APIENTRYP PFNGLSIGNALVKSEMAPHORENVPROC) (GLuint64 vkSemaphore); +typedef void (APIENTRYP PFNGLSIGNALVKFENCENVPROC) (GLuint64 vkFence); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawVkImageNV (GLuint64 vkImage, GLuint sampler, GLfloat x0, GLfloat y0, GLfloat x1, GLfloat y1, GLfloat z, GLfloat s0, GLfloat t0, GLfloat s1, GLfloat t1); +GLAPI GLVULKANPROCNV APIENTRY glGetVkProcAddrNV (const GLchar *name); +GLAPI void APIENTRY glWaitVkSemaphoreNV (GLuint64 vkSemaphore); +GLAPI void APIENTRY glSignalVkSemaphoreNV (GLuint64 vkSemaphore); +GLAPI void APIENTRY glSignalVkFenceNV (GLuint64 vkFence); +#endif +#endif /* GL_NV_draw_vulkan_image */ + #ifndef GL_NV_evaluators #define GL_NV_evaluators 1 #define GL_EVAL_2D_NV 0x86C0 @@ -9194,6 +10056,10 @@ GLAPI void APIENTRY glGetProgramNamedParameterdvNV (GLuint id, GLsizei len, cons #define GL_NV_fragment_program_option 1 #endif /* GL_NV_fragment_program_option */ +#ifndef GL_NV_fragment_shader_barycentric +#define GL_NV_fragment_shader_barycentric 1 +#endif /* GL_NV_fragment_shader_barycentric */ + #ifndef GL_NV_fragment_shader_interlock #define GL_NV_fragment_shader_interlock 1 #endif /* GL_NV_fragment_shader_interlock */ @@ -9209,11 +10075,11 @@ GLAPI void APIENTRY glGetProgramNamedParameterdvNV (GLuint id, GLsizei len, cons #define GL_COVERAGE_MODULATION_NV 0x9332 #define GL_COVERAGE_MODULATION_TABLE_SIZE_NV 0x9333 typedef void (APIENTRYP PFNGLCOVERAGEMODULATIONTABLENVPROC) (GLsizei n, const GLfloat *v); -typedef void (APIENTRYP PFNGLGETCOVERAGEMODULATIONTABLENVPROC) (GLsizei bufsize, GLfloat *v); +typedef void (APIENTRYP PFNGLGETCOVERAGEMODULATIONTABLENVPROC) (GLsizei bufSize, GLfloat *v); typedef void (APIENTRYP PFNGLCOVERAGEMODULATIONNVPROC) (GLenum components); #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glCoverageModulationTableNV (GLsizei n, const GLfloat *v); -GLAPI void APIENTRY glGetCoverageModulationTableNV (GLsizei bufsize, GLfloat *v); +GLAPI void APIENTRY glGetCoverageModulationTableNV (GLsizei bufSize, GLfloat *v); GLAPI void APIENTRY glCoverageModulationNV (GLenum components); #endif #endif /* GL_NV_framebuffer_mixed_samples */ @@ -9253,6 +10119,41 @@ GLAPI void APIENTRY glFramebufferTextureFaceEXT (GLenum target, GLenum attachmen #define GL_NV_geometry_shader_passthrough 1 #endif /* GL_NV_geometry_shader_passthrough */ +#ifndef GL_NV_gpu_multicast +#define GL_NV_gpu_multicast 1 +#define GL_PER_GPU_STORAGE_BIT_NV 0x0800 +#define GL_MULTICAST_GPUS_NV 0x92BA +#define GL_RENDER_GPU_MASK_NV 0x9558 +#define GL_PER_GPU_STORAGE_NV 0x9548 +#define GL_MULTICAST_PROGRAMMABLE_SAMPLE_LOCATION_NV 0x9549 +typedef void (APIENTRYP PFNGLRENDERGPUMASKNVPROC) (GLbitfield mask); +typedef void (APIENTRYP PFNGLMULTICASTBUFFERSUBDATANVPROC) (GLbitfield gpuMask, GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data); +typedef void (APIENTRYP PFNGLMULTICASTCOPYBUFFERSUBDATANVPROC) (GLuint readGpu, GLbitfield writeGpuMask, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +typedef void (APIENTRYP PFNGLMULTICASTCOPYIMAGESUBDATANVPROC) (GLuint srcGpu, GLbitfield dstGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +typedef void (APIENTRYP PFNGLMULTICASTBLITFRAMEBUFFERNVPROC) (GLuint srcGpu, GLuint dstGpu, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef void (APIENTRYP PFNGLMULTICASTFRAMEBUFFERSAMPLELOCATIONSFVNVPROC) (GLuint gpu, GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v); +typedef void (APIENTRYP PFNGLMULTICASTBARRIERNVPROC) (void); +typedef void (APIENTRYP PFNGLMULTICASTWAITSYNCNVPROC) (GLuint signalGpu, GLbitfield waitGpuMask); +typedef void (APIENTRYP PFNGLMULTICASTGETQUERYOBJECTIVNVPROC) (GLuint gpu, GLuint id, GLenum pname, GLint *params); +typedef void (APIENTRYP PFNGLMULTICASTGETQUERYOBJECTUIVNVPROC) (GLuint gpu, GLuint id, GLenum pname, GLuint *params); +typedef void (APIENTRYP PFNGLMULTICASTGETQUERYOBJECTI64VNVPROC) (GLuint gpu, GLuint id, GLenum pname, GLint64 *params); +typedef void (APIENTRYP PFNGLMULTICASTGETQUERYOBJECTUI64VNVPROC) (GLuint gpu, GLuint id, GLenum pname, GLuint64 *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glRenderGpuMaskNV (GLbitfield mask); +GLAPI void APIENTRY glMulticastBufferSubDataNV (GLbitfield gpuMask, GLuint buffer, GLintptr offset, GLsizeiptr size, const void *data); +GLAPI void APIENTRY glMulticastCopyBufferSubDataNV (GLuint readGpu, GLbitfield writeGpuMask, GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +GLAPI void APIENTRY glMulticastCopyImageSubDataNV (GLuint srcGpu, GLbitfield dstGpuMask, GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +GLAPI void APIENTRY glMulticastBlitFramebufferNV (GLuint srcGpu, GLuint dstGpu, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +GLAPI void APIENTRY glMulticastFramebufferSampleLocationsfvNV (GLuint gpu, GLuint framebuffer, GLuint start, GLsizei count, const GLfloat *v); +GLAPI void APIENTRY glMulticastBarrierNV (void); +GLAPI void APIENTRY glMulticastWaitSyncNV (GLuint signalGpu, GLbitfield waitGpuMask); +GLAPI void APIENTRY glMulticastGetQueryObjectivNV (GLuint gpu, GLuint id, GLenum pname, GLint *params); +GLAPI void APIENTRY glMulticastGetQueryObjectuivNV (GLuint gpu, GLuint id, GLenum pname, GLuint *params); +GLAPI void APIENTRY glMulticastGetQueryObjecti64vNV (GLuint gpu, GLuint id, GLenum pname, GLint64 *params); +GLAPI void APIENTRY glMulticastGetQueryObjectui64vNV (GLuint gpu, GLuint id, GLenum pname, GLuint64 *params); +#endif +#endif /* GL_NV_gpu_multicast */ + #ifndef GL_NV_gpu_program4 #define GL_NV_gpu_program4 1 #define GL_MIN_PROGRAM_TEXEL_OFFSET_NV 0x8904 @@ -9357,12 +10258,6 @@ typedef void (APIENTRYP PFNGLMULTITEXCOORD3HNVPROC) (GLenum target, GLhalfNV s, typedef void (APIENTRYP PFNGLMULTITEXCOORD3HVNVPROC) (GLenum target, const GLhalfNV *v); typedef void (APIENTRYP PFNGLMULTITEXCOORD4HNVPROC) (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); typedef void (APIENTRYP PFNGLMULTITEXCOORD4HVNVPROC) (GLenum target, const GLhalfNV *v); -typedef void (APIENTRYP PFNGLFOGCOORDHNVPROC) (GLhalfNV fog); -typedef void (APIENTRYP PFNGLFOGCOORDHVNVPROC) (const GLhalfNV *fog); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); -typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV *v); -typedef void (APIENTRYP PFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight); -typedef void (APIENTRYP PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV *weight); typedef void (APIENTRYP PFNGLVERTEXATTRIB1HNVPROC) (GLuint index, GLhalfNV x); typedef void (APIENTRYP PFNGLVERTEXATTRIB1HVNVPROC) (GLuint index, const GLhalfNV *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB2HNVPROC) (GLuint index, GLhalfNV x, GLhalfNV y); @@ -9375,6 +10270,12 @@ typedef void (APIENTRYP PFNGLVERTEXATTRIBS1HVNVPROC) (GLuint index, GLsizei n, c typedef void (APIENTRYP PFNGLVERTEXATTRIBS2HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBS3HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); typedef void (APIENTRYP PFNGLVERTEXATTRIBS4HVNVPROC) (GLuint index, GLsizei n, const GLhalfNV *v); +typedef void (APIENTRYP PFNGLFOGCOORDHNVPROC) (GLhalfNV fog); +typedef void (APIENTRYP PFNGLFOGCOORDHVNVPROC) (const GLhalfNV *fog); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HNVPROC) (GLhalfNV red, GLhalfNV green, GLhalfNV blue); +typedef void (APIENTRYP PFNGLSECONDARYCOLOR3HVNVPROC) (const GLhalfNV *v); +typedef void (APIENTRYP PFNGLVERTEXWEIGHTHNVPROC) (GLhalfNV weight); +typedef void (APIENTRYP PFNGLVERTEXWEIGHTHVNVPROC) (const GLhalfNV *weight); #ifdef GL_GLEXT_PROTOTYPES GLAPI void APIENTRY glVertex2hNV (GLhalfNV x, GLhalfNV y); GLAPI void APIENTRY glVertex2hvNV (const GLhalfNV *v); @@ -9404,12 +10305,6 @@ GLAPI void APIENTRY glMultiTexCoord3hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLAPI void APIENTRY glMultiTexCoord3hvNV (GLenum target, const GLhalfNV *v); GLAPI void APIENTRY glMultiTexCoord4hNV (GLenum target, GLhalfNV s, GLhalfNV t, GLhalfNV r, GLhalfNV q); GLAPI void APIENTRY glMultiTexCoord4hvNV (GLenum target, const GLhalfNV *v); -GLAPI void APIENTRY glFogCoordhNV (GLhalfNV fog); -GLAPI void APIENTRY glFogCoordhvNV (const GLhalfNV *fog); -GLAPI void APIENTRY glSecondaryColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue); -GLAPI void APIENTRY glSecondaryColor3hvNV (const GLhalfNV *v); -GLAPI void APIENTRY glVertexWeighthNV (GLhalfNV weight); -GLAPI void APIENTRY glVertexWeighthvNV (const GLhalfNV *weight); GLAPI void APIENTRY glVertexAttrib1hNV (GLuint index, GLhalfNV x); GLAPI void APIENTRY glVertexAttrib1hvNV (GLuint index, const GLhalfNV *v); GLAPI void APIENTRY glVertexAttrib2hNV (GLuint index, GLhalfNV x, GLhalfNV y); @@ -9422,6 +10317,12 @@ GLAPI void APIENTRY glVertexAttribs1hvNV (GLuint index, GLsizei n, const GLhalfN GLAPI void APIENTRY glVertexAttribs2hvNV (GLuint index, GLsizei n, const GLhalfNV *v); GLAPI void APIENTRY glVertexAttribs3hvNV (GLuint index, GLsizei n, const GLhalfNV *v); GLAPI void APIENTRY glVertexAttribs4hvNV (GLuint index, GLsizei n, const GLhalfNV *v); +GLAPI void APIENTRY glFogCoordhNV (GLhalfNV fog); +GLAPI void APIENTRY glFogCoordhvNV (const GLhalfNV *fog); +GLAPI void APIENTRY glSecondaryColor3hNV (GLhalfNV red, GLhalfNV green, GLhalfNV blue); +GLAPI void APIENTRY glSecondaryColor3hvNV (const GLhalfNV *v); +GLAPI void APIENTRY glVertexWeighthNV (GLhalfNV weight); +GLAPI void APIENTRY glVertexWeighthvNV (const GLhalfNV *weight); #endif #endif /* GL_NV_half_float */ @@ -9431,9 +10332,9 @@ GLAPI void APIENTRY glVertexAttribs4hvNV (GLuint index, GLsizei n, const GLhalfN #define GL_SUPERSAMPLE_SCALE_X_NV 0x9372 #define GL_SUPERSAMPLE_SCALE_Y_NV 0x9373 #define GL_CONFORMANT_NV 0x9374 -typedef void (APIENTRYP PFNGLGETINTERNALFORMATSAMPLEIVNVPROC) (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params); +typedef void (APIENTRYP PFNGLGETINTERNALFORMATSAMPLEIVNVPROC) (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei count, GLint *params); #ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glGetInternalformatSampleivNV (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params); +GLAPI void APIENTRY glGetInternalformatSampleivNV (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei count, GLint *params); #endif #endif /* GL_NV_internalformat_sample_query */ @@ -9443,6 +10344,110 @@ GLAPI void APIENTRY glGetInternalformatSampleivNV (GLenum target, GLenum interna #define GL_MAX_SPOT_EXPONENT_NV 0x8505 #endif /* GL_NV_light_max_exponent */ +#ifndef GL_NV_memory_attachment +#define GL_NV_memory_attachment 1 +#define GL_ATTACHED_MEMORY_OBJECT_NV 0x95A4 +#define GL_ATTACHED_MEMORY_OFFSET_NV 0x95A5 +#define GL_MEMORY_ATTACHABLE_ALIGNMENT_NV 0x95A6 +#define GL_MEMORY_ATTACHABLE_SIZE_NV 0x95A7 +#define GL_MEMORY_ATTACHABLE_NV 0x95A8 +#define GL_DETACHED_MEMORY_INCARNATION_NV 0x95A9 +#define GL_DETACHED_TEXTURES_NV 0x95AA +#define GL_DETACHED_BUFFERS_NV 0x95AB +#define GL_MAX_DETACHED_TEXTURES_NV 0x95AC +#define GL_MAX_DETACHED_BUFFERS_NV 0x95AD +typedef void (APIENTRYP PFNGLGETMEMORYOBJECTDETACHEDRESOURCESUIVNVPROC) (GLuint memory, GLenum pname, GLint first, GLsizei count, GLuint *params); +typedef void (APIENTRYP PFNGLRESETMEMORYOBJECTPARAMETERNVPROC) (GLuint memory, GLenum pname); +typedef void (APIENTRYP PFNGLTEXATTACHMEMORYNVPROC) (GLenum target, GLuint memory, GLuint64 offset); +typedef void (APIENTRYP PFNGLBUFFERATTACHMEMORYNVPROC) (GLenum target, GLuint memory, GLuint64 offset); +typedef void (APIENTRYP PFNGLTEXTUREATTACHMEMORYNVPROC) (GLuint texture, GLuint memory, GLuint64 offset); +typedef void (APIENTRYP PFNGLNAMEDBUFFERATTACHMEMORYNVPROC) (GLuint buffer, GLuint memory, GLuint64 offset); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGetMemoryObjectDetachedResourcesuivNV (GLuint memory, GLenum pname, GLint first, GLsizei count, GLuint *params); +GLAPI void APIENTRY glResetMemoryObjectParameterNV (GLuint memory, GLenum pname); +GLAPI void APIENTRY glTexAttachMemoryNV (GLenum target, GLuint memory, GLuint64 offset); +GLAPI void APIENTRY glBufferAttachMemoryNV (GLenum target, GLuint memory, GLuint64 offset); +GLAPI void APIENTRY glTextureAttachMemoryNV (GLuint texture, GLuint memory, GLuint64 offset); +GLAPI void APIENTRY glNamedBufferAttachMemoryNV (GLuint buffer, GLuint memory, GLuint64 offset); +#endif +#endif /* GL_NV_memory_attachment */ + +#ifndef GL_NV_memory_object_sparse +#define GL_NV_memory_object_sparse 1 +typedef void (APIENTRYP PFNGLBUFFERPAGECOMMITMENTMEMNVPROC) (GLenum target, GLintptr offset, GLsizeiptr size, GLuint memory, GLuint64 memOffset, GLboolean commit); +typedef void (APIENTRYP PFNGLTEXPAGECOMMITMENTMEMNVPROC) (GLenum target, GLint layer, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset, GLboolean commit); +typedef void (APIENTRYP PFNGLNAMEDBUFFERPAGECOMMITMENTMEMNVPROC) (GLuint buffer, GLintptr offset, GLsizeiptr size, GLuint memory, GLuint64 memOffset, GLboolean commit); +typedef void (APIENTRYP PFNGLTEXTUREPAGECOMMITMENTMEMNVPROC) (GLuint texture, GLint layer, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset, GLboolean commit); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBufferPageCommitmentMemNV (GLenum target, GLintptr offset, GLsizeiptr size, GLuint memory, GLuint64 memOffset, GLboolean commit); +GLAPI void APIENTRY glTexPageCommitmentMemNV (GLenum target, GLint layer, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset, GLboolean commit); +GLAPI void APIENTRY glNamedBufferPageCommitmentMemNV (GLuint buffer, GLintptr offset, GLsizeiptr size, GLuint memory, GLuint64 memOffset, GLboolean commit); +GLAPI void APIENTRY glTexturePageCommitmentMemNV (GLuint texture, GLint layer, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLuint memory, GLuint64 offset, GLboolean commit); +#endif +#endif /* GL_NV_memory_object_sparse */ + +#ifndef GL_NV_mesh_shader +#define GL_NV_mesh_shader 1 +#define GL_MESH_SHADER_NV 0x9559 +#define GL_TASK_SHADER_NV 0x955A +#define GL_MAX_MESH_UNIFORM_BLOCKS_NV 0x8E60 +#define GL_MAX_MESH_TEXTURE_IMAGE_UNITS_NV 0x8E61 +#define GL_MAX_MESH_IMAGE_UNIFORMS_NV 0x8E62 +#define GL_MAX_MESH_UNIFORM_COMPONENTS_NV 0x8E63 +#define GL_MAX_MESH_ATOMIC_COUNTER_BUFFERS_NV 0x8E64 +#define GL_MAX_MESH_ATOMIC_COUNTERS_NV 0x8E65 +#define GL_MAX_MESH_SHADER_STORAGE_BLOCKS_NV 0x8E66 +#define GL_MAX_COMBINED_MESH_UNIFORM_COMPONENTS_NV 0x8E67 +#define GL_MAX_TASK_UNIFORM_BLOCKS_NV 0x8E68 +#define GL_MAX_TASK_TEXTURE_IMAGE_UNITS_NV 0x8E69 +#define GL_MAX_TASK_IMAGE_UNIFORMS_NV 0x8E6A +#define GL_MAX_TASK_UNIFORM_COMPONENTS_NV 0x8E6B +#define GL_MAX_TASK_ATOMIC_COUNTER_BUFFERS_NV 0x8E6C +#define GL_MAX_TASK_ATOMIC_COUNTERS_NV 0x8E6D +#define GL_MAX_TASK_SHADER_STORAGE_BLOCKS_NV 0x8E6E +#define GL_MAX_COMBINED_TASK_UNIFORM_COMPONENTS_NV 0x8E6F +#define GL_MAX_MESH_WORK_GROUP_INVOCATIONS_NV 0x95A2 +#define GL_MAX_TASK_WORK_GROUP_INVOCATIONS_NV 0x95A3 +#define GL_MAX_MESH_TOTAL_MEMORY_SIZE_NV 0x9536 +#define GL_MAX_TASK_TOTAL_MEMORY_SIZE_NV 0x9537 +#define GL_MAX_MESH_OUTPUT_VERTICES_NV 0x9538 +#define GL_MAX_MESH_OUTPUT_PRIMITIVES_NV 0x9539 +#define GL_MAX_TASK_OUTPUT_COUNT_NV 0x953A +#define GL_MAX_DRAW_MESH_TASKS_COUNT_NV 0x953D +#define GL_MAX_MESH_VIEWS_NV 0x9557 +#define GL_MESH_OUTPUT_PER_VERTEX_GRANULARITY_NV 0x92DF +#define GL_MESH_OUTPUT_PER_PRIMITIVE_GRANULARITY_NV 0x9543 +#define GL_MAX_MESH_WORK_GROUP_SIZE_NV 0x953B +#define GL_MAX_TASK_WORK_GROUP_SIZE_NV 0x953C +#define GL_MESH_WORK_GROUP_SIZE_NV 0x953E +#define GL_TASK_WORK_GROUP_SIZE_NV 0x953F +#define GL_MESH_VERTICES_OUT_NV 0x9579 +#define GL_MESH_PRIMITIVES_OUT_NV 0x957A +#define GL_MESH_OUTPUT_TYPE_NV 0x957B +#define GL_UNIFORM_BLOCK_REFERENCED_BY_MESH_SHADER_NV 0x959C +#define GL_UNIFORM_BLOCK_REFERENCED_BY_TASK_SHADER_NV 0x959D +#define GL_REFERENCED_BY_MESH_SHADER_NV 0x95A0 +#define GL_REFERENCED_BY_TASK_SHADER_NV 0x95A1 +#define GL_MESH_SHADER_BIT_NV 0x00000040 +#define GL_TASK_SHADER_BIT_NV 0x00000080 +#define GL_MESH_SUBROUTINE_NV 0x957C +#define GL_TASK_SUBROUTINE_NV 0x957D +#define GL_MESH_SUBROUTINE_UNIFORM_NV 0x957E +#define GL_TASK_SUBROUTINE_UNIFORM_NV 0x957F +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_MESH_SHADER_NV 0x959E +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TASK_SHADER_NV 0x959F +typedef void (APIENTRYP PFNGLDRAWMESHTASKSNVPROC) (GLuint first, GLuint count); +typedef void (APIENTRYP PFNGLDRAWMESHTASKSINDIRECTNVPROC) (GLintptr indirect); +typedef void (APIENTRYP PFNGLMULTIDRAWMESHTASKSINDIRECTNVPROC) (GLintptr indirect, GLsizei drawcount, GLsizei stride); +typedef void (APIENTRYP PFNGLMULTIDRAWMESHTASKSINDIRECTCOUNTNVPROC) (GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glDrawMeshTasksNV (GLuint first, GLuint count); +GLAPI void APIENTRY glDrawMeshTasksIndirectNV (GLintptr indirect); +GLAPI void APIENTRY glMultiDrawMeshTasksIndirectNV (GLintptr indirect, GLsizei drawcount, GLsizei stride); +GLAPI void APIENTRY glMultiDrawMeshTasksIndirectCountNV (GLintptr indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +#endif +#endif /* GL_NV_mesh_shader */ + #ifndef GL_NV_multisample_coverage #define GL_NV_multisample_coverage 1 #endif /* GL_NV_multisample_coverage */ @@ -9720,11 +10725,11 @@ typedef void (APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHNVPROC) (GLuint path, GLenu typedef void (APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask, GLenum coverMode); typedef void (APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); typedef void (APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); -typedef GLenum (APIENTRYP PFNGLPATHGLYPHINDEXRANGENVPROC) (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]); +typedef GLenum (APIENTRYP PFNGLPATHGLYPHINDEXRANGENVPROC) (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint *baseAndCount); typedef GLenum (APIENTRYP PFNGLPATHGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); typedef GLenum (APIENTRYP PFNGLPATHMEMORYGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); typedef void (APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC) (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs); -typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCEFVNVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params); +typedef void (APIENTRYP PFNGLGETPROGRAMRESOURCEFVNVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei count, GLsizei *length, GLfloat *params); typedef void (APIENTRYP PFNGLPATHCOLORGENNVPROC) (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat *coeffs); typedef void (APIENTRYP PFNGLPATHTEXGENNVPROC) (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat *coeffs); typedef void (APIENTRYP PFNGLPATHFOGGENNVPROC) (GLenum genMode); @@ -9785,11 +10790,11 @@ GLAPI void APIENTRY glStencilThenCoverFillPathNV (GLuint path, GLenum fillMode, GLAPI void APIENTRY glStencilThenCoverStrokePathNV (GLuint path, GLint reference, GLuint mask, GLenum coverMode); GLAPI void APIENTRY glStencilThenCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); GLAPI void APIENTRY glStencilThenCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); -GLAPI GLenum APIENTRY glPathGlyphIndexRangeNV (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]); +GLAPI GLenum APIENTRY glPathGlyphIndexRangeNV (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint *baseAndCount); GLAPI GLenum APIENTRY glPathGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); GLAPI GLenum APIENTRY glPathMemoryGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); GLAPI void APIENTRY glProgramPathFragmentInputGenNV (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs); -GLAPI void APIENTRY glGetProgramResourcefvNV (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params); +GLAPI void APIENTRY glGetProgramResourcefvNV (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei count, GLsizei *length, GLfloat *params); GLAPI void APIENTRY glPathColorGenNV (GLenum color, GLenum genMode, GLenum colorFormat, const GLfloat *coeffs); GLAPI void APIENTRY glPathTexGenNV (GLenum texCoordSet, GLenum genMode, GLint components, const GLfloat *coeffs); GLAPI void APIENTRY glPathFogGenNV (GLenum genMode); @@ -9870,6 +10875,38 @@ GLAPI void APIENTRY glPrimitiveRestartIndexNV (GLuint index); #endif #endif /* GL_NV_primitive_restart */ +#ifndef GL_NV_primitive_shading_rate +#define GL_NV_primitive_shading_rate 1 +#define GL_SHADING_RATE_IMAGE_PER_PRIMITIVE_NV 0x95B1 +#define GL_SHADING_RATE_IMAGE_PALETTE_COUNT_NV 0x95B2 +#endif /* GL_NV_primitive_shading_rate */ + +#ifndef GL_NV_query_resource +#define GL_NV_query_resource 1 +#define GL_QUERY_RESOURCE_TYPE_VIDMEM_ALLOC_NV 0x9540 +#define GL_QUERY_RESOURCE_MEMTYPE_VIDMEM_NV 0x9542 +#define GL_QUERY_RESOURCE_SYS_RESERVED_NV 0x9544 +#define GL_QUERY_RESOURCE_TEXTURE_NV 0x9545 +#define GL_QUERY_RESOURCE_RENDERBUFFER_NV 0x9546 +#define GL_QUERY_RESOURCE_BUFFEROBJECT_NV 0x9547 +typedef GLint (APIENTRYP PFNGLQUERYRESOURCENVPROC) (GLenum queryType, GLint tagId, GLuint count, GLint *buffer); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLint APIENTRY glQueryResourceNV (GLenum queryType, GLint tagId, GLuint count, GLint *buffer); +#endif +#endif /* GL_NV_query_resource */ + +#ifndef GL_NV_query_resource_tag +#define GL_NV_query_resource_tag 1 +typedef void (APIENTRYP PFNGLGENQUERYRESOURCETAGNVPROC) (GLsizei n, GLint *tagIds); +typedef void (APIENTRYP PFNGLDELETEQUERYRESOURCETAGNVPROC) (GLsizei n, const GLint *tagIds); +typedef void (APIENTRYP PFNGLQUERYRESOURCETAGNVPROC) (GLint tagId, const GLchar *tagString); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glGenQueryResourceTagNV (GLsizei n, GLint *tagIds); +GLAPI void APIENTRY glDeleteQueryResourceTagNV (GLsizei n, const GLint *tagIds); +GLAPI void APIENTRY glQueryResourceTagNV (GLint tagId, const GLchar *tagString); +#endif +#endif /* GL_NV_query_resource_tag */ + #ifndef GL_NV_register_combiners #define GL_NV_register_combiners 1 #define GL_REGISTER_COMBINERS_NV 0x8522 @@ -9962,6 +10999,16 @@ GLAPI void APIENTRY glGetCombinerStageParameterfvNV (GLenum stage, GLenum pname, #endif #endif /* GL_NV_register_combiners2 */ +#ifndef GL_NV_representative_fragment_test +#define GL_NV_representative_fragment_test 1 +#define GL_REPRESENTATIVE_FRAGMENT_TEST_NV 0x937F +#endif /* GL_NV_representative_fragment_test */ + +#ifndef GL_NV_robustness_video_memory_purge +#define GL_NV_robustness_video_memory_purge 1 +#define GL_PURGED_CONTEXT_RESET_NV 0x92BB +#endif /* GL_NV_robustness_video_memory_purge */ + #ifndef GL_NV_sample_locations #define GL_NV_sample_locations 1 #define GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV 0x933D @@ -9986,6 +11033,18 @@ GLAPI void APIENTRY glResolveDepthValuesNV (void); #define GL_NV_sample_mask_override_coverage 1 #endif /* GL_NV_sample_mask_override_coverage */ +#ifndef GL_NV_scissor_exclusive +#define GL_NV_scissor_exclusive 1 +#define GL_SCISSOR_TEST_EXCLUSIVE_NV 0x9555 +#define GL_SCISSOR_BOX_EXCLUSIVE_NV 0x9556 +typedef void (APIENTRYP PFNGLSCISSOREXCLUSIVENVPROC) (GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (APIENTRYP PFNGLSCISSOREXCLUSIVEARRAYVNVPROC) (GLuint first, GLsizei count, const GLint *v); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glScissorExclusiveNV (GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI void APIENTRY glScissorExclusiveArrayvNV (GLuint first, GLsizei count, const GLint *v); +#endif +#endif /* GL_NV_scissor_exclusive */ + #ifndef GL_NV_shader_atomic_counters #define GL_NV_shader_atomic_counters 1 #endif /* GL_NV_shader_atomic_counters */ @@ -9994,6 +11053,10 @@ GLAPI void APIENTRY glResolveDepthValuesNV (void); #define GL_NV_shader_atomic_float 1 #endif /* GL_NV_shader_atomic_float */ +#ifndef GL_NV_shader_atomic_float64 +#define GL_NV_shader_atomic_float64 1 +#endif /* GL_NV_shader_atomic_float64 */ + #ifndef GL_NV_shader_atomic_fp16_vector #define GL_NV_shader_atomic_fp16_vector 1 #endif /* GL_NV_shader_atomic_fp16_vector */ @@ -10046,6 +11109,15 @@ GLAPI void APIENTRY glProgramUniformui64vNV (GLuint program, GLint location, GLs #define GL_NV_shader_storage_buffer_object 1 #endif /* GL_NV_shader_storage_buffer_object */ +#ifndef GL_NV_shader_subgroup_partitioned +#define GL_NV_shader_subgroup_partitioned 1 +#define GL_SUBGROUP_FEATURE_PARTITIONED_BIT_NV 0x00000100 +#endif /* GL_NV_shader_subgroup_partitioned */ + +#ifndef GL_NV_shader_texture_footprint +#define GL_NV_shader_texture_footprint 1 +#endif /* GL_NV_shader_texture_footprint */ + #ifndef GL_NV_shader_thread_group #define GL_NV_shader_thread_group 1 #define GL_WARP_SIZE_NV 0x9339 @@ -10057,6 +11129,51 @@ GLAPI void APIENTRY glProgramUniformui64vNV (GLuint program, GLint location, GLs #define GL_NV_shader_thread_shuffle 1 #endif /* GL_NV_shader_thread_shuffle */ +#ifndef GL_NV_shading_rate_image +#define GL_NV_shading_rate_image 1 +#define GL_SHADING_RATE_IMAGE_NV 0x9563 +#define GL_SHADING_RATE_NO_INVOCATIONS_NV 0x9564 +#define GL_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV 0x9565 +#define GL_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV 0x9566 +#define GL_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV 0x9567 +#define GL_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV 0x9568 +#define GL_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV 0x9569 +#define GL_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV 0x956A +#define GL_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV 0x956B +#define GL_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV 0x956C +#define GL_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV 0x956D +#define GL_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV 0x956E +#define GL_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV 0x956F +#define GL_SHADING_RATE_IMAGE_BINDING_NV 0x955B +#define GL_SHADING_RATE_IMAGE_TEXEL_WIDTH_NV 0x955C +#define GL_SHADING_RATE_IMAGE_TEXEL_HEIGHT_NV 0x955D +#define GL_SHADING_RATE_IMAGE_PALETTE_SIZE_NV 0x955E +#define GL_MAX_COARSE_FRAGMENT_SAMPLES_NV 0x955F +#define GL_SHADING_RATE_SAMPLE_ORDER_DEFAULT_NV 0x95AE +#define GL_SHADING_RATE_SAMPLE_ORDER_PIXEL_MAJOR_NV 0x95AF +#define GL_SHADING_RATE_SAMPLE_ORDER_SAMPLE_MAJOR_NV 0x95B0 +typedef void (APIENTRYP PFNGLBINDSHADINGRATEIMAGENVPROC) (GLuint texture); +typedef void (APIENTRYP PFNGLGETSHADINGRATEIMAGEPALETTENVPROC) (GLuint viewport, GLuint entry, GLenum *rate); +typedef void (APIENTRYP PFNGLGETSHADINGRATESAMPLELOCATIONIVNVPROC) (GLenum rate, GLuint samples, GLuint index, GLint *location); +typedef void (APIENTRYP PFNGLSHADINGRATEIMAGEBARRIERNVPROC) (GLboolean synchronize); +typedef void (APIENTRYP PFNGLSHADINGRATEIMAGEPALETTENVPROC) (GLuint viewport, GLuint first, GLsizei count, const GLenum *rates); +typedef void (APIENTRYP PFNGLSHADINGRATESAMPLEORDERNVPROC) (GLenum order); +typedef void (APIENTRYP PFNGLSHADINGRATESAMPLEORDERCUSTOMNVPROC) (GLenum rate, GLuint samples, const GLint *locations); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glBindShadingRateImageNV (GLuint texture); +GLAPI void APIENTRY glGetShadingRateImagePaletteNV (GLuint viewport, GLuint entry, GLenum *rate); +GLAPI void APIENTRY glGetShadingRateSampleLocationivNV (GLenum rate, GLuint samples, GLuint index, GLint *location); +GLAPI void APIENTRY glShadingRateImageBarrierNV (GLboolean synchronize); +GLAPI void APIENTRY glShadingRateImagePaletteNV (GLuint viewport, GLuint first, GLsizei count, const GLenum *rates); +GLAPI void APIENTRY glShadingRateSampleOrderNV (GLenum order); +GLAPI void APIENTRY glShadingRateSampleOrderCustomNV (GLenum rate, GLuint samples, const GLint *locations); +#endif +#endif /* GL_NV_shading_rate_image */ + +#ifndef GL_NV_stereo_view_rendering +#define GL_NV_stereo_view_rendering 1 +#endif /* GL_NV_stereo_view_rendering */ + #ifndef GL_NV_tessellation_program5 #define GL_NV_tessellation_program5 1 #define GL_MAX_PROGRAM_PATCH_ATTRIBS_NV 0x86D8 @@ -10133,6 +11250,10 @@ GLAPI void APIENTRY glTextureImage3DMultisampleCoverageNV (GLuint texture, GLenu #define GL_MAX_RECTANGLE_TEXTURE_SIZE_NV 0x84F8 #endif /* GL_NV_texture_rectangle */ +#ifndef GL_NV_texture_rectangle_compressed +#define GL_NV_texture_rectangle_compressed 1 +#endif /* GL_NV_texture_rectangle_compressed */ + #ifndef GL_NV_texture_shader #define GL_NV_texture_shader 1 #define GL_OFFSET_TEXTURE_RECTANGLE_NV 0x864C @@ -10236,6 +11357,23 @@ GLAPI void APIENTRY glTextureImage3DMultisampleCoverageNV (GLuint texture, GLenu #define GL_FORCE_BLUE_TO_ONE_NV 0x8860 #endif /* GL_NV_texture_shader3 */ +#ifndef GL_NV_timeline_semaphore +#define GL_NV_timeline_semaphore 1 +#define GL_TIMELINE_SEMAPHORE_VALUE_NV 0x9595 +#define GL_SEMAPHORE_TYPE_NV 0x95B3 +#define GL_SEMAPHORE_TYPE_BINARY_NV 0x95B4 +#define GL_SEMAPHORE_TYPE_TIMELINE_NV 0x95B5 +#define GL_MAX_TIMELINE_SEMAPHORE_VALUE_DIFFERENCE_NV 0x95B6 +typedef void (APIENTRYP PFNGLCREATESEMAPHORESNVPROC) (GLsizei n, GLuint *semaphores); +typedef void (APIENTRYP PFNGLSEMAPHOREPARAMETERIVNVPROC) (GLuint semaphore, GLenum pname, const GLint *params); +typedef void (APIENTRYP PFNGLGETSEMAPHOREPARAMETERIVNVPROC) (GLuint semaphore, GLenum pname, GLint *params); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glCreateSemaphoresNV (GLsizei n, GLuint *semaphores); +GLAPI void APIENTRY glSemaphoreParameterivNV (GLuint semaphore, GLenum pname, const GLint *params); +GLAPI void APIENTRY glGetSemaphoreParameterivNV (GLuint semaphore, GLenum pname, GLint *params); +#endif +#endif /* GL_NV_timeline_semaphore */ + #ifndef GL_NV_transform_feedback #define GL_NV_transform_feedback 1 #define GL_BACK_PRIMARY_COLOR_NV 0x8C77 @@ -10321,6 +11459,10 @@ GLAPI void APIENTRY glDrawTransformFeedbackNV (GLenum mode, GLuint id); #endif #endif /* GL_NV_transform_feedback2 */ +#ifndef GL_NV_uniform_buffer_std430_layout +#define GL_NV_uniform_buffer_std430_layout 1 +#endif /* GL_NV_uniform_buffer_std430_layout */ + #ifndef GL_NV_uniform_buffer_unified_memory #define GL_NV_uniform_buffer_unified_memory 1 #define GL_UNIFORM_BUFFER_UNIFIED_NV 0x936E @@ -10341,7 +11483,7 @@ typedef GLvdpauSurfaceNV (APIENTRYP PFNGLVDPAUREGISTERVIDEOSURFACENVPROC) (const typedef GLvdpauSurfaceNV (APIENTRYP PFNGLVDPAUREGISTEROUTPUTSURFACENVPROC) (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); typedef GLboolean (APIENTRYP PFNGLVDPAUISSURFACENVPROC) (GLvdpauSurfaceNV surface); typedef void (APIENTRYP PFNGLVDPAUUNREGISTERSURFACENVPROC) (GLvdpauSurfaceNV surface); -typedef void (APIENTRYP PFNGLVDPAUGETSURFACEIVNVPROC) (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); +typedef void (APIENTRYP PFNGLVDPAUGETSURFACEIVNVPROC) (GLvdpauSurfaceNV surface, GLenum pname, GLsizei count, GLsizei *length, GLint *values); typedef void (APIENTRYP PFNGLVDPAUSURFACEACCESSNVPROC) (GLvdpauSurfaceNV surface, GLenum access); typedef void (APIENTRYP PFNGLVDPAUMAPSURFACESNVPROC) (GLsizei numSurfaces, const GLvdpauSurfaceNV *surfaces); typedef void (APIENTRYP PFNGLVDPAUUNMAPSURFACESNVPROC) (GLsizei numSurface, const GLvdpauSurfaceNV *surfaces); @@ -10352,13 +11494,21 @@ GLAPI GLvdpauSurfaceNV APIENTRY glVDPAURegisterVideoSurfaceNV (const void *vdpSu GLAPI GLvdpauSurfaceNV APIENTRY glVDPAURegisterOutputSurfaceNV (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames); GLAPI GLboolean APIENTRY glVDPAUIsSurfaceNV (GLvdpauSurfaceNV surface); GLAPI void APIENTRY glVDPAUUnregisterSurfaceNV (GLvdpauSurfaceNV surface); -GLAPI void APIENTRY glVDPAUGetSurfaceivNV (GLvdpauSurfaceNV surface, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); +GLAPI void APIENTRY glVDPAUGetSurfaceivNV (GLvdpauSurfaceNV surface, GLenum pname, GLsizei count, GLsizei *length, GLint *values); GLAPI void APIENTRY glVDPAUSurfaceAccessNV (GLvdpauSurfaceNV surface, GLenum access); GLAPI void APIENTRY glVDPAUMapSurfacesNV (GLsizei numSurfaces, const GLvdpauSurfaceNV *surfaces); GLAPI void APIENTRY glVDPAUUnmapSurfacesNV (GLsizei numSurface, const GLvdpauSurfaceNV *surfaces); #endif #endif /* GL_NV_vdpau_interop */ +#ifndef GL_NV_vdpau_interop2 +#define GL_NV_vdpau_interop2 1 +typedef GLvdpauSurfaceNV (APIENTRYP PFNGLVDPAUREGISTERVIDEOSURFACEWITHPICTURESTRUCTURENVPROC) (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames, GLboolean isFrameStructure); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI GLvdpauSurfaceNV APIENTRY glVDPAURegisterVideoSurfaceWithPictureStructureNV (const void *vdpSurface, GLenum target, GLsizei numTextureNames, const GLuint *textureNames, GLboolean isFrameStructure); +#endif +#endif /* GL_NV_vdpau_interop2 */ + #ifndef GL_NV_vertex_array_range #define GL_NV_vertex_array_range 1 #define GL_VERTEX_ARRAY_RANGE_NV 0x851D @@ -10714,54 +11864,6 @@ GLAPI void APIENTRY glVertexAttribs4ubvNV (GLuint index, GLsizei count, const GL #ifndef GL_NV_vertex_program4 #define GL_NV_vertex_program4 1 #define GL_VERTEX_ATTRIB_ARRAY_INTEGER_NV 0x88FD -typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IEXTPROC) (GLuint index, GLint x); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IEXTPROC) (GLuint index, GLint x, GLint y); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IEXTPROC) (GLuint index, GLint x, GLint y, GLint z); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IEXTPROC) (GLuint index, GLint x, GLint y, GLint z, GLint w); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIEXTPROC) (GLuint index, GLuint x); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIEXTPROC) (GLuint index, GLuint x, GLuint y); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIEXTPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI1IVEXTPROC) (GLuint index, const GLint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI2IVEXTPROC) (GLuint index, const GLint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI3IVEXTPROC) (GLuint index, const GLint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4IVEXTPROC) (GLuint index, const GLint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI1UIVEXTPROC) (GLuint index, const GLuint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI2UIVEXTPROC) (GLuint index, const GLuint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI3UIVEXTPROC) (GLuint index, const GLuint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIVEXTPROC) (GLuint index, const GLuint *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4BVEXTPROC) (GLuint index, const GLbyte *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4SVEXTPROC) (GLuint index, const GLshort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UBVEXTPROC) (GLuint index, const GLubyte *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBI4USVEXTPROC) (GLuint index, const GLushort *v); -typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTEREXTPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIIVEXTPROC) (GLuint index, GLenum pname, GLint *params); -typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIUIVEXTPROC) (GLuint index, GLenum pname, GLuint *params); -#ifdef GL_GLEXT_PROTOTYPES -GLAPI void APIENTRY glVertexAttribI1iEXT (GLuint index, GLint x); -GLAPI void APIENTRY glVertexAttribI2iEXT (GLuint index, GLint x, GLint y); -GLAPI void APIENTRY glVertexAttribI3iEXT (GLuint index, GLint x, GLint y, GLint z); -GLAPI void APIENTRY glVertexAttribI4iEXT (GLuint index, GLint x, GLint y, GLint z, GLint w); -GLAPI void APIENTRY glVertexAttribI1uiEXT (GLuint index, GLuint x); -GLAPI void APIENTRY glVertexAttribI2uiEXT (GLuint index, GLuint x, GLuint y); -GLAPI void APIENTRY glVertexAttribI3uiEXT (GLuint index, GLuint x, GLuint y, GLuint z); -GLAPI void APIENTRY glVertexAttribI4uiEXT (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -GLAPI void APIENTRY glVertexAttribI1ivEXT (GLuint index, const GLint *v); -GLAPI void APIENTRY glVertexAttribI2ivEXT (GLuint index, const GLint *v); -GLAPI void APIENTRY glVertexAttribI3ivEXT (GLuint index, const GLint *v); -GLAPI void APIENTRY glVertexAttribI4ivEXT (GLuint index, const GLint *v); -GLAPI void APIENTRY glVertexAttribI1uivEXT (GLuint index, const GLuint *v); -GLAPI void APIENTRY glVertexAttribI2uivEXT (GLuint index, const GLuint *v); -GLAPI void APIENTRY glVertexAttribI3uivEXT (GLuint index, const GLuint *v); -GLAPI void APIENTRY glVertexAttribI4uivEXT (GLuint index, const GLuint *v); -GLAPI void APIENTRY glVertexAttribI4bvEXT (GLuint index, const GLbyte *v); -GLAPI void APIENTRY glVertexAttribI4svEXT (GLuint index, const GLshort *v); -GLAPI void APIENTRY glVertexAttribI4ubvEXT (GLuint index, const GLubyte *v); -GLAPI void APIENTRY glVertexAttribI4usvEXT (GLuint index, const GLushort *v); -GLAPI void APIENTRY glVertexAttribIPointerEXT (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); -GLAPI void APIENTRY glGetVertexAttribIivEXT (GLuint index, GLenum pname, GLint *params); -GLAPI void APIENTRY glGetVertexAttribIuivEXT (GLuint index, GLenum pname, GLuint *params); -#endif #endif /* GL_NV_vertex_program4 */ #ifndef GL_NV_video_capture @@ -10823,6 +11925,30 @@ GLAPI void APIENTRY glVideoCaptureStreamParameterdvNV (GLuint video_capture_slot #endif #endif /* GL_NV_video_capture */ +#ifndef GL_NV_viewport_array2 +#define GL_NV_viewport_array2 1 +#endif /* GL_NV_viewport_array2 */ + +#ifndef GL_NV_viewport_swizzle +#define GL_NV_viewport_swizzle 1 +#define GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV 0x9350 +#define GL_VIEWPORT_SWIZZLE_NEGATIVE_X_NV 0x9351 +#define GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV 0x9352 +#define GL_VIEWPORT_SWIZZLE_NEGATIVE_Y_NV 0x9353 +#define GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV 0x9354 +#define GL_VIEWPORT_SWIZZLE_NEGATIVE_Z_NV 0x9355 +#define GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV 0x9356 +#define GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV 0x9357 +#define GL_VIEWPORT_SWIZZLE_X_NV 0x9358 +#define GL_VIEWPORT_SWIZZLE_Y_NV 0x9359 +#define GL_VIEWPORT_SWIZZLE_Z_NV 0x935A +#define GL_VIEWPORT_SWIZZLE_W_NV 0x935B +typedef void (APIENTRYP PFNGLVIEWPORTSWIZZLENVPROC) (GLuint index, GLenum swizzlex, GLenum swizzley, GLenum swizzlez, GLenum swizzlew); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glViewportSwizzleNV (GLuint index, GLenum swizzlex, GLenum swizzley, GLenum swizzlez, GLenum swizzlew); +#endif +#endif /* GL_NV_viewport_swizzle */ + #ifndef GL_OML_interlace #define GL_OML_interlace 1 #define GL_INTERLACE_OML 0x8980 @@ -10845,6 +11971,24 @@ GLAPI void APIENTRY glVideoCaptureStreamParameterdvNV (GLuint video_capture_slot #define GL_FORMAT_SUBSAMPLE_244_244_OML 0x8983 #endif /* GL_OML_subsample */ +#ifndef GL_OVR_multiview +#define GL_OVR_multiview 1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR 0x9630 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR 0x9632 +#define GL_MAX_VIEWS_OVR 0x9631 +#define GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR 0x9633 +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews); +typedef void (APIENTRYP PFNGLNAMEDFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC) (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews); +#ifdef GL_GLEXT_PROTOTYPES +GLAPI void APIENTRY glFramebufferTextureMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews); +GLAPI void APIENTRY glNamedFramebufferTextureMultiviewOVR (GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews); +#endif +#endif /* GL_OVR_multiview */ + +#ifndef GL_OVR_multiview2 +#define GL_OVR_multiview2 1 +#endif /* GL_OVR_multiview2 */ + #ifndef GL_PGI_misc_hints #define GL_PGI_misc_hints 1 #define GL_PREFER_DOUBLEBUFFER_HINT_PGI 0x1A1F8 @@ -11401,10 +12545,10 @@ GLAPI void APIENTRY glReferencePlaneSGIX (const GLdouble *equation); #ifndef GL_SGIX_resample #define GL_SGIX_resample 1 -#define GL_PACK_RESAMPLE_SGIX 0x842C -#define GL_UNPACK_RESAMPLE_SGIX 0x842D -#define GL_RESAMPLE_REPLICATE_SGIX 0x842E -#define GL_RESAMPLE_ZERO_FILL_SGIX 0x842F +#define GL_PACK_RESAMPLE_SGIX 0x842E +#define GL_UNPACK_RESAMPLE_SGIX 0x842F +#define GL_RESAMPLE_REPLICATE_SGIX 0x8433 +#define GL_RESAMPLE_ZERO_FILL_SGIX 0x8434 #define GL_RESAMPLE_DECIMATE_SGIX 0x8430 #endif /* GL_SGIX_resample */ @@ -11767,4 +12911,4 @@ GLAPI void APIENTRY glReplacementCodeuiTexCoord2fColor4fNormal3fVertex3fvSUN (co } #endif -#endif \ No newline at end of file +#endif diff --git a/codemp/rd-rend2/glsl/bokeh.glsl b/shared/rd-rend2/glsl/bokeh.glsl similarity index 100% rename from codemp/rd-rend2/glsl/bokeh.glsl rename to shared/rd-rend2/glsl/bokeh.glsl diff --git a/codemp/rd-rend2/glsl/calclevels4x.glsl b/shared/rd-rend2/glsl/calclevels4x.glsl similarity index 100% rename from codemp/rd-rend2/glsl/calclevels4x.glsl rename to shared/rd-rend2/glsl/calclevels4x.glsl diff --git a/codemp/rd-rend2/glsl/compact.cpp b/shared/rd-rend2/glsl/compact.cpp similarity index 100% rename from codemp/rd-rend2/glsl/compact.cpp rename to shared/rd-rend2/glsl/compact.cpp diff --git a/codemp/rd-rend2/glsl/depthblur.glsl b/shared/rd-rend2/glsl/depthblur.glsl similarity index 100% rename from codemp/rd-rend2/glsl/depthblur.glsl rename to shared/rd-rend2/glsl/depthblur.glsl diff --git a/codemp/rd-rend2/glsl/dglow_downsample.glsl b/shared/rd-rend2/glsl/dglow_downsample.glsl similarity index 100% rename from codemp/rd-rend2/glsl/dglow_downsample.glsl rename to shared/rd-rend2/glsl/dglow_downsample.glsl diff --git a/codemp/rd-rend2/glsl/dglow_upsample.glsl b/shared/rd-rend2/glsl/dglow_upsample.glsl similarity index 100% rename from codemp/rd-rend2/glsl/dglow_upsample.glsl rename to shared/rd-rend2/glsl/dglow_upsample.glsl diff --git a/codemp/rd-rend2/glsl/down4x.glsl b/shared/rd-rend2/glsl/down4x.glsl similarity index 100% rename from codemp/rd-rend2/glsl/down4x.glsl rename to shared/rd-rend2/glsl/down4x.glsl diff --git a/codemp/rd-rend2/glsl/fogpass.glsl b/shared/rd-rend2/glsl/fogpass.glsl similarity index 96% rename from codemp/rd-rend2/glsl/fogpass.glsl rename to shared/rd-rend2/glsl/fogpass.glsl index ab69f6de99..2b27f0cefb 100644 --- a/codemp/rd-rend2/glsl/fogpass.glsl +++ b/shared/rd-rend2/glsl/fogpass.glsl @@ -27,12 +27,11 @@ layout(std140) uniform Entity mat4 u_ModelMatrix; vec4 u_LocalLightOrigin; vec3 u_AmbientLight; - float u_LocalLightRadius; + float u_entityTime; vec3 u_DirectedLight; float u_FXVolumetricBase; vec3 u_ModelLightDir; float u_VertexLerp; - vec3 u_LocalViewOrigin; }; layout(std140) uniform ShaderInstance @@ -226,10 +225,10 @@ void main() normal = DeformNormal( position, normal ); #endif - mat4 MVP = u_viewProjectionMatrix * u_ModelMatrix; - gl_Position = MVP * vec4(position, 1.0); + vec4 wsPosition = u_ModelMatrix * vec4(position, 1.0); + gl_Position = u_viewProjectionMatrix * wsPosition; - var_WSPosition = (u_ModelMatrix * vec4(position, 1.0)).xyz; + var_WSPosition = wsPosition.xyz; #if defined(USE_ALPHA_TEST) var_TexCoords = attr_TexCoord0; #endif @@ -263,7 +262,7 @@ struct Fog layout(std140) uniform Fogs { int u_NumFogs; - Fog u_Fogs[16]; + Fog u_Fogs[MAX_GPU_FOGS]; }; layout(std140) uniform Camera @@ -281,12 +280,11 @@ layout(std140) uniform Entity mat4 u_ModelMatrix; vec4 u_LocalLightOrigin; vec3 u_AmbientLight; - float u_LocalLightRadius; + float u_entityTime; vec3 u_DirectedLight; float u_FXVolumetricBase; vec3 u_ModelLightDir; float u_VertexLerp; - vec3 u_LocalViewOrigin; }; uniform int u_FogIndex; diff --git a/codemp/rd-rend2/glsl/gaussian_blur.glsl b/shared/rd-rend2/glsl/gaussian_blur.glsl similarity index 100% rename from codemp/rd-rend2/glsl/gaussian_blur.glsl rename to shared/rd-rend2/glsl/gaussian_blur.glsl diff --git a/codemp/rd-rend2/glsl/generic.glsl b/shared/rd-rend2/glsl/generic.glsl similarity index 90% rename from codemp/rd-rend2/glsl/generic.glsl rename to shared/rd-rend2/glsl/generic.glsl index 9d814303a7..20561730b0 100644 --- a/codemp/rd-rend2/glsl/generic.glsl +++ b/shared/rd-rend2/glsl/generic.glsl @@ -46,13 +46,11 @@ layout(std140) uniform Entity mat4 u_ModelMatrix; vec4 u_LocalLightOrigin; vec3 u_AmbientLight; - float u_LocalLightRadius; + float u_entityTime; vec3 u_DirectedLight; float u_FXVolumetricBase; vec3 u_ModelLightDir; float u_VertexLerp; - vec3 u_LocalViewOrigin; - float u_entityTime; }; #if defined(USE_DEFORM_VERTEXES) || defined(USE_RGBAGEN) @@ -285,13 +283,32 @@ vec2 GenTexCoords(int TCGen, vec3 position, vec3 normal, vec3 TCGenVector0, vec3 case TCGEN_ENVIRONMENT_MAPPED: { - vec3 viewer = normalize(u_LocalViewOrigin - position); + vec3 localOrigin = (inverse(u_ModelMatrix) * vec4(u_ViewOrigin, 1.0)).xyz; + vec3 viewer = normalize(localOrigin - position); vec2 ref = reflect(viewer, normal).yz; tex.s = ref.x * -0.5 + 0.5; tex.t = ref.y * 0.5 + 0.5; } break; + case TCGEN_ENVIRONMENT_MAPPED_SP: + { + vec3 localOrigin = (inverse(u_ModelMatrix) * vec4(u_ViewOrigin, 1.0)).xyz; + vec3 viewer = normalize(localOrigin - position); + vec2 ref = reflect(viewer, normal).xy; + tex.s = ref.x * -0.5; + tex.t = ref.y * -0.5; + } + break; + + case TCGEN_ENVIRONMENT_MAPPED_SP_FP: + { + vec2 ref = reflect(u_ModelLightDir.xyz, normal).xy; + tex.s = ref.x * -0.5 + 0.5 * u_ModelLightDir.x; + tex.t = ref.y * -0.5 + 0.5 * u_ModelLightDir.y; + } + break; + case TCGEN_VECTOR: { tex = vec2(dot(position, TCGenVector0), dot(position, TCGenVector1)); @@ -364,10 +381,12 @@ vec4 CalcColor(vec3 position, vec3 normal) return color; } - vec3 viewer = u_LocalViewOrigin - position; + vec3 localOrigin = (inverse(u_ModelMatrix) * vec4(u_ViewOrigin, 1.0)).xyz; + vec3 viewer = localOrigin - position; if (u_AlphaGen == AGEN_LIGHTING_SPECULAR) { + // TODO: Handle specular on player models and misc_model_statics correctly vec3 lightDir = normalize(vec3(-960.0, 1980.0, 96.0) - position); vec3 reflected = -reflect(lightDir, normal); @@ -421,11 +440,11 @@ void main() normal = DeformNormal( position, normal ); #endif - mat4 MVP = u_viewProjectionMatrix * u_ModelMatrix; - gl_Position = MVP * vec4(position, 1.0); + vec4 wsPosition = u_ModelMatrix * vec4(position, 1.0); + gl_Position = u_viewProjectionMatrix * wsPosition; #if defined(USE_TCGEN) - vec2 tex = GenTexCoords(u_TCGen0, position, normal, u_TCGen0Vector0, u_TCGen0Vector1); + vec2 tex = GenTexCoords(u_TCGen0, position.xyz, normal, u_TCGen0Vector0, u_TCGen0Vector1); #else vec2 tex = attr_TexCoord0.st; #endif @@ -448,14 +467,14 @@ void main() else { #if defined(USE_RGBAGEN) - var_Color = CalcColor(position, normal); + var_Color = CalcColor(position.xyz, normal); #else var_Color = u_VertColor * attr_Color + u_BaseColor; #endif } #if defined(USE_FOG) - var_WSPosition = (u_ModelMatrix * vec4(position, 1.0)).xyz; + var_WSPosition = wsPosition.xyz; #endif } @@ -472,7 +491,7 @@ struct Fog layout(std140) uniform Fogs { int u_NumFogs; - Fog u_Fogs[16]; + Fog u_Fogs[MAX_GPU_FOGS]; }; uniform vec4 u_FogColorMask; @@ -492,13 +511,11 @@ layout(std140) uniform Entity mat4 u_ModelMatrix; vec4 u_LocalLightOrigin; vec3 u_AmbientLight; - float u_LocalLightRadius; + float u_entityTime; vec3 u_DirectedLight; float u_FXVolumetricBase; vec3 u_ModelLightDir; float u_VertexLerp; - vec3 u_LocalViewOrigin; - float u_entityTime; }; uniform sampler2D u_DiffuseMap; @@ -506,6 +523,8 @@ uniform sampler2D u_DiffuseMap; uniform int u_AlphaTestType; #endif uniform int u_FogIndex; +// x = glow out, y = deluxe, z = screen shadow, w = cube +uniform vec4 u_EnableTextures; in vec2 var_DiffuseTex; in vec4 var_Color; @@ -551,7 +570,7 @@ float CalcFog(in vec3 viewOrigin, in vec3 position, in Fog fog) void main() { vec4 color = texture(u_DiffuseMap, var_DiffuseTex); - color.a *= var_Color.a; + color *= var_Color; #if defined(USE_ALPHA_TEST) if (u_AlphaTestType == ALPHA_TEST_GT0) { @@ -581,11 +600,6 @@ void main() color *= vec4(1.0) - u_FogColorMask * fogFactor; #endif - out_Color = vec4(color.rgb * var_Color.rgb, color.a); - -#if defined(USE_GLOW_BUFFER) - out_Glow = out_Color; -#else - out_Glow = vec4(0.0); -#endif + out_Color = color; + out_Glow = mix(vec4(0.0, 0.0, 0.0, color.a), color, u_EnableTextures.x); } diff --git a/codemp/rd-rend2/glsl/lightall.glsl b/shared/rd-rend2/glsl/lightall.glsl similarity index 96% rename from codemp/rd-rend2/glsl/lightall.glsl rename to shared/rd-rend2/glsl/lightall.glsl index 33f54bba68..05752f2565 100644 --- a/codemp/rd-rend2/glsl/lightall.glsl +++ b/shared/rd-rend2/glsl/lightall.glsl @@ -45,13 +45,11 @@ layout(std140) uniform Entity mat4 u_ModelMatrix; vec4 u_LocalLightOrigin; vec3 u_AmbientLight; - float u_LocalLightRadius; + float u_entityTime; vec3 u_DirectedLight; float u_FXVolumetricBase; vec3 u_ModelLightDir; float u_VertexLerp; - vec3 u_LocalViewOrigin; - float u_entityTime; }; #if defined(USE_SKELETAL_ANIMATION) @@ -159,13 +157,32 @@ vec2 GenTexCoords(int TCGen, vec3 position, vec3 normal, vec3 TCGenVector0, vec3 case TCGEN_ENVIRONMENT_MAPPED: { - vec3 viewer = normalize(u_LocalViewOrigin - position); + vec3 localOrigin = (inverse(u_ModelMatrix) * vec4(u_ViewOrigin, 1.0)).xyz; + vec3 viewer = normalize(localOrigin - position); vec2 ref = reflect(viewer, normal).yz; tex.s = ref.x * -0.5 + 0.5; tex.t = ref.y * 0.5 + 0.5; } break; + case TCGEN_ENVIRONMENT_MAPPED_SP: + { + vec3 localOrigin = (inverse(u_ModelMatrix) * vec4(u_ViewOrigin, 1.0)).xyz; + vec3 viewer = normalize(localOrigin - position); + vec2 ref = reflect(viewer, normal).xy; + tex.s = ref.x * -0.5; + tex.t = ref.y * -0.5; + } + break; + + case TCGEN_ENVIRONMENT_MAPPED_SP_FP: + { + vec2 ref = reflect(u_ModelLightDir.xyz, normal).xy; + tex.s = ref.x * -0.5 + 0.5 * u_ModelLightDir.x; + tex.t = ref.y * -0.5 + 0.5 * u_ModelLightDir.y; + } + break; + case TCGEN_VECTOR: { tex = vec2(dot(position, TCGenVector0), dot(position, TCGenVector1)); @@ -241,8 +258,10 @@ void main() #endif #endif + vec4 wsPosition = u_ModelMatrix * vec4(position, 1.0); + #if defined(USE_TCGEN) - vec2 texCoords = GenTexCoords(u_TCGen0, position, normal, u_TCGen0Vector0, u_TCGen0Vector1); + vec2 texCoords = GenTexCoords(u_TCGen0, position.xyz, normal, u_TCGen0Vector0, u_TCGen0Vector1); #else vec2 texCoords = attr_TexCoord0.st; #endif @@ -255,17 +274,16 @@ void main() vec4 disintegration = CalcColor(position); - mat4 MVP = u_viewProjectionMatrix * u_ModelMatrix; - gl_Position = MVP * vec4(position, 1.0); + gl_Position = u_viewProjectionMatrix * wsPosition; - position = (u_ModelMatrix * vec4(position, 1.0)).xyz; + position = wsPosition.xyz; normal = normalize(mat3(u_ModelMatrix) * normal); #if defined(PER_PIXEL_LIGHTING) tangent = normalize(mat3(u_ModelMatrix) * tangent); #endif #if defined(USE_LIGHT_VECTOR) - vec3 L = u_LocalLightOrigin.xyz - (position * u_LocalLightOrigin.w); + vec3 L = u_LocalLightOrigin.xyz; #elif defined(PER_PIXEL_LIGHTING) vec3 L = attr_LightDirection * 2.0 - vec3(1.0); L = (u_ModelMatrix * vec4(L, 0.0)).xyz; @@ -293,7 +311,7 @@ void main() float sqrLightDist = dot(L, L); float NL = clamp(dot(normal, L) / sqrt(sqrLightDist), 0.0, 1.0); - var_Color.rgb *= u_DirectedLight * NL + u_AmbientLight; + var_Color.rgb *= mix(u_DirectedLight, u_AmbientLight, NL); #endif } var_Color *= disintegration; @@ -350,13 +368,11 @@ layout(std140) uniform Entity mat4 u_ModelMatrix; vec4 u_LocalLightOrigin; vec3 u_AmbientLight; - float u_LocalLightRadius; + float u_entityTime; vec3 u_DirectedLight; float u_FXVolumetricBase; vec3 u_ModelLightDir; float u_VertexLerp; - vec3 u_LocalViewOrigin; - float u_entityTime; }; struct Light @@ -411,10 +427,8 @@ uniform samplerCube u_CubeMap; uniform sampler2D u_EnvBrdfMap; #endif -#if defined(USE_NORMALMAP) || defined(USE_DELUXEMAP) || defined(USE_SPECULARMAP) || defined(USE_CUBEMAP) -// y = deluxe, w = cube +// x = glow out, y = deluxe, z = screen shadow, w = cube uniform vec4 u_EnableTextures; -#endif uniform vec4 u_NormalScale; uniform vec4 u_SpecularScale; @@ -906,7 +920,7 @@ vec3 CalcDynamicLightContribution( vec3 outColor = vec3(0.0); vec3 position = viewOrigin - viewDir; - for ( int i = 0; i < u_NumLights; i++ ) + for ( int i = 0; i < min(u_NumLights, MAX_DLIGHTS); i++ ) { if ( ( u_LightMask & ( 1 << i ) ) == 0 ) { continue; @@ -1179,10 +1193,5 @@ void main() #endif out_Color.a = diffuse.a; - -#if defined(USE_GLOW_BUFFER) - out_Glow = out_Color; -#else - out_Glow = vec4(0.0, 0.0, 0.0, out_Color.a); -#endif + out_Glow = mix(vec4(0.0, 0.0, 0.0, out_Color.a), out_Color, u_EnableTextures.x); } diff --git a/codemp/rd-rend2/glsl/prefilterEnvMap.glsl b/shared/rd-rend2/glsl/prefilterEnvMap.glsl similarity index 100% rename from codemp/rd-rend2/glsl/prefilterEnvMap.glsl rename to shared/rd-rend2/glsl/prefilterEnvMap.glsl diff --git a/codemp/rd-rend2/glsl/pshadow.glsl b/shared/rd-rend2/glsl/pshadow.glsl similarity index 100% rename from codemp/rd-rend2/glsl/pshadow.glsl rename to shared/rd-rend2/glsl/pshadow.glsl diff --git a/codemp/rd-rend2/glsl/refraction.glsl b/shared/rd-rend2/glsl/refraction.glsl similarity index 93% rename from codemp/rd-rend2/glsl/refraction.glsl rename to shared/rd-rend2/glsl/refraction.glsl index 5f5eabcd48..eebfb51839 100644 --- a/codemp/rd-rend2/glsl/refraction.glsl +++ b/shared/rd-rend2/glsl/refraction.glsl @@ -43,13 +43,11 @@ layout(std140) uniform Entity mat4 u_ModelMatrix; vec4 u_LocalLightOrigin; vec3 u_AmbientLight; - float u_LocalLightRadius; + float u_entityTime; vec3 u_DirectedLight; float u_FXVolumetricBase; vec3 u_ModelLightDir; float u_VertexLerp; - vec3 u_LocalViewOrigin; - float u_entityTime; }; #if defined(USE_DEFORM_VERTEXES) || defined(USE_RGBAGEN) @@ -231,11 +229,25 @@ vec2 GenTexCoords(int TCGen, vec3 position, vec3 normal, vec3 TCGenVector0, vec3 } else if (TCGen == TCGEN_ENVIRONMENT_MAPPED) { - vec3 viewer = normalize(u_LocalViewOrigin - position); + vec3 viewer = normalize(u_ViewOrigin - position); vec2 ref = reflect(viewer, normal).yz; tex.s = ref.x * -0.5 + 0.5; tex.t = ref.y * 0.5 + 0.5; } + else if (TCGen == TCGEN_ENVIRONMENT_MAPPED_SP) + { + vec3 viewer = normalize(u_ViewOrigin - position); + vec2 ref = reflect(viewer, normal).xy; + tex.s = ref.x * -0.5; + tex.t = ref.y * -0.5; + } + + else if (TCGen == TCGEN_ENVIRONMENT_MAPPED_SP_FP) + { + vec2 ref = reflect(u_ModelLightDir.xyz, normal).xy; + tex.s = ref.x * -0.5 + 0.5 * u_ModelLightDir.x; + tex.t = ref.y * -0.5 + 0.5 * u_ModelLightDir.y; + } else if (TCGen == TCGEN_VECTOR) { tex = vec2(dot(position, TCGenVector0), dot(position, TCGenVector1)); @@ -274,7 +286,7 @@ vec4 CalcColor(vec3 position, vec3 normal) color.rgb = clamp(u_DirectedLight * incoming + u_AmbientLight, 0.0, 1.0); } - vec3 viewer = u_LocalViewOrigin - position; + vec3 viewer = u_ViewOrigin - position; if (u_AlphaGen == AGEN_LIGHTING_SPECULAR) { @@ -335,11 +347,12 @@ void main() normal = DeformNormal( position, normal ); #endif + vec3 wsPosition = mat3(u_ModelMatrix) * position; mat4 MVP = u_viewProjectionMatrix * u_ModelMatrix; gl_Position = MVP * vec4(position, 1.0); #if defined(USE_TCGEN) - vec2 tex = GenTexCoords(u_TCGen0, position, normal, u_TCGen0Vector0, u_TCGen0Vector1); + vec2 tex = GenTexCoords(u_TCGen0, wsPosition.xyz, normal, u_TCGen0Vector0, u_TCGen0Vector1); #else vec2 tex = attr_TexCoord0.st; #endif @@ -368,7 +381,6 @@ void main() #endif } - vec3 ws_Position = mat3(u_ModelMatrix) * position; vec3 ws_Normal = normalize(mat3(u_ModelMatrix) * normal); vec3 ws_ViewDir = (u_ViewForward + u_ViewLeft * -gl_Position.x) + u_ViewUp * gl_Position.y; @@ -381,17 +393,17 @@ void main() mat3 inverseModel = inverse(mat3(u_ModelMatrix)); vec3 refraction_vec = normalize(refract(ws_ViewDir, ws_Normal, etaR)); - vec3 new_pos = (distance * refraction_vec) + ws_Position; + vec3 new_pos = (distance * refraction_vec) + wsPosition.xyz; var_RefractPosR = vec4(inverseModel * new_pos, 1.0); var_RefractPosR = MVP * var_RefractPosR; refraction_vec = normalize(refract(ws_ViewDir, ws_Normal, etaG)); - new_pos = (distance * refraction_vec) + ws_Position; + new_pos = (distance * refraction_vec) + wsPosition.xyz; var_RefractPosG = vec4(inverseModel * new_pos, 1.0); var_RefractPosG = MVP * var_RefractPosG; refraction_vec = normalize(refract(ws_ViewDir, ws_Normal, etaB)); - new_pos = (distance * refraction_vec) + ws_Position; + new_pos = (distance * refraction_vec) + wsPosition.xyz; var_RefractPosB = vec4(inverseModel * new_pos, 1.0); var_RefractPosB = MVP * var_RefractPosB; } @@ -414,13 +426,11 @@ layout(std140) uniform Entity mat4 u_ModelMatrix; vec4 u_LocalLightOrigin; vec3 u_AmbientLight; - float u_LocalLightRadius; + float u_entityTime; vec3 u_DirectedLight; float u_FXVolumetricBase; vec3 u_ModelLightDir; float u_VertexLerp; - vec3 u_LocalViewOrigin; - float u_entityTime; }; uniform sampler2D u_TextureMap; diff --git a/codemp/rd-rend2/glsl/shadowvolume.glsl b/shared/rd-rend2/glsl/shadowvolume.glsl similarity index 60% rename from codemp/rd-rend2/glsl/shadowvolume.glsl rename to shared/rd-rend2/glsl/shadowvolume.glsl index fe7d45d3c3..5d3d95bd3d 100644 --- a/codemp/rd-rend2/glsl/shadowvolume.glsl +++ b/shared/rd-rend2/glsl/shadowvolume.glsl @@ -12,12 +12,11 @@ layout(std140) uniform Entity mat4 u_ModelMatrix; vec4 u_LocalLightOrigin; vec3 u_AmbientLight; - float u_LocalLightRadius; + float u_entityTime; vec3 u_DirectedLight; float u_FXVolumetricBase; vec3 u_ModelLightDir; float u_VertexLerp; - vec3 u_LocalViewOrigin; }; #if defined(USE_SKELETAL_ANIMATION) @@ -76,29 +75,15 @@ layout(std140) uniform Entity mat4 u_ModelMatrix; vec4 u_LocalLightOrigin; vec3 u_AmbientLight; - float u_LocalLightRadius; + float u_entityTime; vec3 u_DirectedLight; float u_FXVolumetricBase; vec3 u_ModelLightDir; float u_VertexLerp; - vec3 u_LocalViewOrigin; }; in vec3 var_Position[]; -void quad(in vec3 first, in vec3 second, in vec3 L, in mat4 MVP) -{ - gl_Position = MVP * vec4(first, 1.0); - EmitVertex(); - gl_Position = MVP * vec4(first - L, 1.0); - EmitVertex(); - gl_Position = MVP * vec4(second, 1.0); - EmitVertex(); - gl_Position = MVP * vec4(second - L, 1.0); - EmitVertex(); - EndPrimitive(); -} - void main() { vec3 BmA = var_Position[1].xyz - var_Position[0].xyz; @@ -107,28 +92,63 @@ void main() mat4 MVP = u_viewProjectionMatrix * u_ModelMatrix; if (dot(cross(BmA,CmA), -u_ModelLightDir.xyz) > 0.0) { - vec3 L = u_ModelLightDir.xyz*u_LocalLightRadius; - - // front cap - gl_Position = MVP * vec4(var_Position[0].xyz, 1.0); + vec3 L = u_ModelLightDir.xyz*u_LocalLightOrigin.w; + + vec4 positions[6] = vec4[6]( + u_viewProjectionMatrix * u_ModelMatrix * vec4(var_Position[0], 1.0), + u_viewProjectionMatrix * u_ModelMatrix * vec4(var_Position[1], 1.0), + u_viewProjectionMatrix * u_ModelMatrix * vec4(var_Position[2], 1.0), + u_viewProjectionMatrix * u_ModelMatrix * vec4(var_Position[0] - L, 1.0), + u_viewProjectionMatrix * u_ModelMatrix * vec4(var_Position[1] - L, 1.0), + u_viewProjectionMatrix * u_ModelMatrix * vec4(var_Position[2] - L, 1.0) + ); + + // front cap, avoids z-fighting with other shaders by NOT using the MVP, the other surfaces won't create z-fighting + gl_Position = positions[0]; EmitVertex(); - gl_Position = MVP * vec4(var_Position[1].xyz, 1.0); + gl_Position = positions[1]; EmitVertex(); - gl_Position = MVP * vec4(var_Position[2].xyz, 1.0); + gl_Position = positions[2]; EmitVertex(); EndPrimitive(); // sides - quad(var_Position[0], var_Position[1], L, MVP); - quad(var_Position[1], var_Position[2], L, MVP); - quad(var_Position[2], var_Position[0], L, MVP); + gl_Position = positions[0]; + EmitVertex(); + gl_Position = positions[3]; + EmitVertex(); + gl_Position = positions[1]; + EmitVertex(); + gl_Position = positions[4]; + EmitVertex(); + EndPrimitive(); + + gl_Position = positions[1]; + EmitVertex(); + gl_Position = positions[4]; + EmitVertex(); + gl_Position = positions[2]; + EmitVertex(); + gl_Position = positions[5]; + EmitVertex(); + EndPrimitive(); + gl_Position = positions[2]; + EmitVertex(); + gl_Position = positions[5]; + EmitVertex(); + gl_Position = positions[0]; + EmitVertex(); + gl_Position = positions[3]; + EmitVertex(); + EndPrimitive(); + // back cap - gl_Position = MVP * vec4(var_Position[2].xyz - L, 1.0); + gl_Position = positions[5]; EmitVertex(); - gl_Position = MVP * vec4(var_Position[1].xyz - L, 1.0); + gl_Position = positions[4]; EmitVertex(); - gl_Position = MVP * vec4(var_Position[0].xyz - L, 1.0); + gl_Position = positions[3]; EmitVertex(); EndPrimitive(); } diff --git a/codemp/rd-rend2/glsl/ssao.glsl b/shared/rd-rend2/glsl/ssao.glsl similarity index 100% rename from codemp/rd-rend2/glsl/ssao.glsl rename to shared/rd-rend2/glsl/ssao.glsl diff --git a/codemp/rd-rend2/glsl/surface_sprites.glsl b/shared/rd-rend2/glsl/surface_sprites.glsl similarity index 98% rename from codemp/rd-rend2/glsl/surface_sprites.glsl rename to shared/rd-rend2/glsl/surface_sprites.glsl index 63ec0b321a..5f5eb76b5a 100644 --- a/codemp/rd-rend2/glsl/surface_sprites.glsl +++ b/shared/rd-rend2/glsl/surface_sprites.glsl @@ -176,14 +176,14 @@ struct Fog layout(std140) uniform Fogs { int u_NumFogs; - Fog u_Fogs[16]; + Fog u_Fogs[MAX_GPU_FOGS]; }; uniform int u_FogIndex; uniform vec4 u_FogColorMask; #endif -#if defined(ALPHA_TEST) +#if defined(USE_ALPHA_TEST) uniform int u_AlphaTestType; #endif @@ -223,7 +223,7 @@ float CalcFog(in vec3 viewOrigin, in vec3 position, in Fog fog) void main() { -#if defined(ALPHA_TEST) +#if defined(USE_ALPHA_TEST) float alphaTestValue = 0.5; if (u_AlphaTestType == ALPHA_TEST_GT0) { @@ -256,7 +256,7 @@ void main() } #endif -#if defined(ALPHA_TEST) +#if defined(USE_ALPHA_TEST) if (u_AlphaTestType == ALPHA_TEST_GT0) { if (out_Color.a == 0.0) diff --git a/codemp/rd-rend2/glsl/texturecolor.glsl b/shared/rd-rend2/glsl/texturecolor.glsl similarity index 100% rename from codemp/rd-rend2/glsl/texturecolor.glsl rename to shared/rd-rend2/glsl/texturecolor.glsl diff --git a/codemp/rd-rend2/glsl/tonemap.glsl b/shared/rd-rend2/glsl/tonemap.glsl similarity index 100% rename from codemp/rd-rend2/glsl/tonemap.glsl rename to shared/rd-rend2/glsl/tonemap.glsl diff --git a/codemp/rd-rend2/glsl/weather.glsl b/shared/rd-rend2/glsl/weather.glsl similarity index 97% rename from codemp/rd-rend2/glsl/weather.glsl rename to shared/rd-rend2/glsl/weather.glsl index 0c6eef6372..64280b15aa 100644 --- a/codemp/rd-rend2/glsl/weather.glsl +++ b/shared/rd-rend2/glsl/weather.glsl @@ -18,9 +18,10 @@ void main() attr_Position.z, 1.0); var_Velocity = attr_Color; + var_Velocity.z = min(-0.00001, var_Velocity.z); vec4 velocitiyOffset = u_ViewInfo.y * vec4(-var_Velocity.xy/var_Velocity.z, var_Velocity.z, 0.0); - velocitiyOffset.xyz = mix(vec3(0.0), velocitiyOffset.xyz, float(var_Velocity.z != 0.0)); + velocitiyOffset.xyz = mix(vec3(0.0), velocitiyOffset.xyz, float(attr_Color.z != 0.0)); var_Velocity.z *= u_ViewInfo.z; vec4 depthPosition = u_ShadowMvp * (gl_Position + velocitiyOffset); diff --git a/codemp/rd-rend2/glsl/weatherUpdate.glsl b/shared/rd-rend2/glsl/weatherUpdate.glsl similarity index 100% rename from codemp/rd-rend2/glsl/weatherUpdate.glsl rename to shared/rd-rend2/glsl/weatherUpdate.glsl diff --git a/codemp/rd-rend2/iqm.h b/shared/rd-rend2/iqm.h similarity index 100% rename from codemp/rd-rend2/iqm.h rename to shared/rd-rend2/iqm.h diff --git a/codemp/rd-rend2/json.h b/shared/rd-rend2/json.h similarity index 100% rename from codemp/rd-rend2/json.h rename to shared/rd-rend2/json.h diff --git a/codemp/rd-rend2/qgl.h b/shared/rd-rend2/qgl.h similarity index 99% rename from codemp/rd-rend2/qgl.h rename to shared/rd-rend2/qgl.h index 949413610b..7471d3048f 100644 --- a/codemp/rd-rend2/qgl.h +++ b/shared/rd-rend2/qgl.h @@ -570,6 +570,7 @@ extern PFNGLGETQUERYOBJECTUIVPROC qglGetQueryObjectuiv; // GL state extern PFNGLGETSTRINGIPROC qglGetStringi; +extern PFNGLCOLORMASKIPROC qglColorMaski; // Sync objects and fences extern PFNGLFENCESYNCPROC qglFenceSync; diff --git a/codemp/rd-rend2/stb_image.h b/shared/rd-rend2/stb_image.h similarity index 100% rename from codemp/rd-rend2/stb_image.h rename to shared/rd-rend2/stb_image.h diff --git a/codemp/rd-rend2/tr_allocator.cpp b/shared/rd-rend2/tr_allocator.cpp similarity index 96% rename from codemp/rd-rend2/tr_allocator.cpp rename to shared/rd-rend2/tr_allocator.cpp index 4da0228c8c..d1e555d596 100644 --- a/codemp/rd-rend2/tr_allocator.cpp +++ b/shared/rd-rend2/tr_allocator.cpp @@ -21,7 +21,7 @@ Allocator::Allocator( size_t memorySize, size_t alignment ) #if defined(GLSL_BUILDTOOL) , unalignedBase(malloc(memorySize)) #else - , unalignedBase(Z_Malloc(memorySize, TAG_SHADERTEXT)) + , unalignedBase(R_Malloc(memorySize, TAG_SHADERTEXT)) #endif , alignedBase(PADP(unalignedBase, alignment)) , mark(alignedBase) diff --git a/codemp/rd-rend2/tr_allocator.h b/shared/rd-rend2/tr_allocator.h similarity index 100% rename from codemp/rd-rend2/tr_allocator.h rename to shared/rd-rend2/tr_allocator.h diff --git a/codemp/rd-rend2/tr_animation.cpp b/shared/rd-rend2/tr_animation.cpp similarity index 86% rename from codemp/rd-rend2/tr_animation.cpp rename to shared/rd-rend2/tr_animation.cpp index b8b794901d..1946872f53 100644 --- a/codemp/rd-rend2/tr_animation.cpp +++ b/shared/rd-rend2/tr_animation.cpp @@ -136,7 +136,8 @@ R_MDRComputeFogNum */ int R_MDRComputeFogNum( mdrHeader_t *header, trRefEntity_t *ent ) { - int i, j; + int i; + float frameRadius; fog_t *fog; mdrFrame_t *mdrFrame; vec3_t localOrigin; @@ -151,22 +152,57 @@ int R_MDRComputeFogNum( mdrHeader_t *header, trRefEntity_t *ent ) { // FIXME: non-normalized axis issues mdrFrame = ( mdrFrame_t * ) ( ( byte * ) header + header->ofsFrames + frameSize * ent->e.frame); VectorAdd( ent->e.origin, mdrFrame->localOrigin, localOrigin ); - for ( i = 1 ; i < tr.world->numfogs ; i++ ) { + frameRadius = mdrFrame->radius; +#ifndef REND2_SP + int j; + for (i = 1; i < tr.world->numfogs; i++) { fog = &tr.world->fogs[i]; - for ( j = 0 ; j < 3 ; j++ ) { - if ( localOrigin[j] - mdrFrame->radius >= fog->bounds[1][j] ) { + for (j = 0; j < 3; j++) { + if (localOrigin[j] - frameRadius >= fog->bounds[1][j]) { break; } - if ( localOrigin[j] + mdrFrame->radius <= fog->bounds[0][j] ) { + if (localOrigin[j] + frameRadius <= fog->bounds[0][j]) { break; } } - if ( j == 3 ) { + if (j == 3) { return i; } } - return 0; +#else + int partialFog = 0; + for (i = 1; i < tr.world->numfogs; i++) { + fog = &tr.world->fogs[i]; + if (localOrigin[0] - frameRadius >= fog->bounds[0][0] + && localOrigin[0] + frameRadius <= fog->bounds[1][0] + && localOrigin[1] - frameRadius >= fog->bounds[0][1] + && localOrigin[1] + frameRadius <= fog->bounds[1][1] + && localOrigin[2] - frameRadius >= fog->bounds[0][2] + && localOrigin[2] + frameRadius <= fog->bounds[1][2]) + {//totally inside it + return i; + break; + } + if ((localOrigin[0] - frameRadius >= fog->bounds[0][0] && localOrigin[1] - frameRadius >= fog->bounds[0][1] && localOrigin[2] - frameRadius >= fog->bounds[0][2] && + localOrigin[0] - frameRadius <= fog->bounds[1][0] && localOrigin[1] - frameRadius <= fog->bounds[1][1] && localOrigin[2] - frameRadius <= fog->bounds[1][2]) || + (localOrigin[0] + frameRadius >= fog->bounds[0][0] && localOrigin[1] + frameRadius >= fog->bounds[0][1] && localOrigin[2] + frameRadius >= fog->bounds[0][2] && + localOrigin[0] + frameRadius <= fog->bounds[1][0] && localOrigin[1] + frameRadius <= fog->bounds[1][1] && localOrigin[2] + frameRadius <= fog->bounds[1][2])) + {//partially inside it + //if (tr.refdef.fogIndex == i || R_FogParmsMatch(tr.refdef.fogIndex, i)) + //{//take new one only if it's the same one that the viewpoint is in + // return i; + // break; + //} + //else + if (!partialFog) + {//first partialFog + partialFog = i; + } + } + } + return partialFog; +#endif } diff --git a/codemp/rd-rend2/tr_backend.cpp b/shared/rd-rend2/tr_backend.cpp similarity index 95% rename from codemp/rd-rend2/tr_backend.cpp rename to shared/rd-rend2/tr_backend.cpp index 295223d453..65cd2b5a8d 100644 --- a/codemp/rd-rend2/tr_backend.cpp +++ b/shared/rd-rend2/tr_backend.cpp @@ -95,7 +95,6 @@ void GL_SelectTexture( int unit ) void GL_BindToTMU( image_t *image, int tmu ) { int texnum; - int oldtmu = glState.currenttmu; if (!image) texnum = 0; @@ -272,27 +271,40 @@ void GL_State( uint32_t stateBits ) break; } - qglEnable( GL_BLEND ); + if (!glState.blend) + { + qglEnable(GL_BLEND); + glState.blend = true; + } qglBlendFunc( srcFactor, dstFactor ); } else { - qglDisable( GL_BLEND ); + if (glState.blend) + { + qglDisable(GL_BLEND); + glState.blend = false; + } } } // - // check colormask + // check colormasks // - if ( diff & GLS_COLORMASK_BITS ) + if ( diff & (GLS_COLORMASK_BITS | GLS_COLORMASK_BUF1)) { if ( stateBits & GLS_COLORMASK_BITS ) { qglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); } + else if ( stateBits & GLS_COLORMASK_BUF1 ) + { + qglColorMaski(0, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + qglColorMaski(1, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } else { - qglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); + qglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } } @@ -479,13 +491,28 @@ void GL_SetProjectionMatrix(matrix_t matrix) Matrix16Multiply(glState.projection, glState.modelview, glState.modelviewProjection); } - void GL_SetModelviewMatrix(matrix_t matrix) { Matrix16Copy(matrix, glState.modelview); Matrix16Multiply(glState.projection, glState.modelview, glState.modelviewProjection); } +void GL_SetViewportAndScissor(int viewportX, int viewportY, int viewportWidth, int viewportHeight) +{ + if (glState.viewportOrigin[0] == viewportX && + glState.viewportOrigin[1] == viewportY && + glState.viewportSize[0] == viewportWidth && + glState.viewportSize[1] == viewportHeight) + return; + + qglViewport(viewportX, viewportY, viewportWidth, viewportHeight); + qglScissor(viewportX, viewportY, viewportWidth, viewportHeight); + + glState.viewportOrigin[0] = viewportX; + glState.viewportOrigin[1] = viewportY; + glState.viewportSize[0] = viewportWidth; + glState.viewportSize[1] = viewportHeight; +} /* ================ @@ -505,20 +532,8 @@ static void SetViewportAndScissor( void ) { GL_SetProjectionMatrix( backEnd.viewParms.projectionMatrix ); // set the window clipping - qglViewport( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY, - backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight ); - - if ( !backEnd.viewParms.scissorX && !backEnd.viewParms.scissorY && - !backEnd.viewParms.scissorWidth && !backEnd.viewParms.scissorHeight ) - { - qglScissor( backEnd.viewParms.viewportX, backEnd.viewParms.viewportY, - backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight ); - } - else - { - qglScissor( backEnd.viewParms.scissorX, backEnd.viewParms.scissorY, - backEnd.viewParms.scissorWidth, backEnd.viewParms.scissorHeight ); - } + GL_SetViewportAndScissor(backEnd.viewParms.viewportX, backEnd.viewParms.viewportY, + backEnd.viewParms.viewportWidth, backEnd.viewParms.viewportHeight); } /* @@ -584,7 +599,11 @@ void RB_BeginDrawingView (void) { #endif } - if (tr.refdef.rdflags & RDF_AUTOMAP || (!(backEnd.refdef.rdflags & RDF_NOWORLDMODEL))) + if ( +#ifndef REND2_SP + tr.refdef.rdflags & RDF_AUTOMAP || +#endif + (!(backEnd.refdef.rdflags & RDF_NOWORLDMODEL))) { if (tr.world && tr.world->globalFog) { @@ -915,6 +934,16 @@ SamplerBindingsWriter& SamplerBindingsWriter::AddAnimatedImage( textureBundle_t { int index; +#ifdef REND2_SP + if ((r_fullbright->integer + || tr.refdef.doLAGoggles + || tr.refdef.doFullbright) + && bundle->isLightmap) + { + return AddStaticImage(tr.whiteImage, unit); + } +#endif + if ( bundle->isVideoMap ) { SamplerBinding *binding = &scratch[count]; @@ -1187,8 +1216,6 @@ static void RB_SubmitDrawSurfsForDepthFill( { shader_t *oldShader = nullptr; int oldEntityNum = -1; - int oldSort = -1; - int oldDepthRange = 0; CBoneCache *oldBoneCache = nullptr; drawSurf_t *drawSurf = drawSurfs; @@ -1202,15 +1229,15 @@ static void RB_SubmitDrawSurfsForDepthFill( R_DecomposeSort(drawSurf->sort, &entityNum, &shader, &cubemapIndex, &postRender); assert(shader != nullptr); - if (shader->useSimpleDepthShader == qtrue) - shader = tr.defaultShader; - if (shader->sort != SS_OPAQUE || shader->useDistortion) { // Don't draw yet, let's see what's to come continue; } + if (shader->useSimpleDepthShader == qtrue) + shader = tr.defaultShader; + if (*drawSurf->surface == SF_MDX) { if (((CRenderableSurface*)drawSurf->surface)->boneCache != oldBoneCache) @@ -1246,8 +1273,6 @@ static void RB_SubmitDrawSurfsForDepthFill( oldShader = shader; } - oldSort = drawSurf->sort; - // change the modelview matrix if needed if ( entityNum != oldEntityNum ) { @@ -1276,7 +1301,6 @@ static void RB_SubmitDrawSurfs( int oldEntityNum = -1; int oldSort = -1; int oldFogNum = -1; - int oldDepthRange = 0; int oldDlighted = 0; int oldPostRender = 0; int oldCubemapIndex = -1; @@ -1507,8 +1531,7 @@ void RB_SetGL2D (void) { } // set 2D virtual screen size - qglViewport( 0, 0, width, height ); - qglScissor( 0, 0, width, height ); + GL_SetViewportAndScissor(0, 0, width, height); Matrix16Ortho(0, 640, 480, 0, 0, 1, matrix); GL_SetProjectionMatrix(matrix); @@ -1918,6 +1941,36 @@ static const void *RB_RotatePic2 ( const void *data ) return (const void *)(cmd + 1); } +#ifdef REND2_SP +/* +============= +RB_ScissorPic +============= +*/ +const void *RB_Scissor(const void *data) +{ + const scissorCommand_t *cmd; + + cmd = (const scissorCommand_t *)data; + + if (!backEnd.projection2D) + { + RB_SetGL2D(); + } + + if (cmd->x >= 0) + { + qglScissor(cmd->x, (glConfig.vidHeight - cmd->y - cmd->h), cmd->w, cmd->h); + } + else + { + qglScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight); + } + + return (const void *)(cmd + 1); +} +#endif + /* ============= RB_PrefilterEnvMap @@ -1971,8 +2024,7 @@ static const void *RB_PrefilterEnvMap(const void *data) { GL_BindToTMU(tr.renderCubeImage, TB_CUBEMAP); GLSL_BindProgram(&tr.prefilterEnvMapShader); - qglViewport(0, 0, width, height); - qglScissor(0, 0, width, height); + GL_SetViewportAndScissor(0, 0, width, height); vec4_t viewInfo; VectorSet4(viewInfo, 0, level, roughnessMips, level / roughnessMips); @@ -1994,8 +2046,7 @@ static void RB_RenderSSAO() FBO_Bind(tr.quarterFbo[0]); - qglViewport(0, 0, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height); - qglScissor(0, 0, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height); + GL_SetViewportAndScissor(0, 0, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height); GL_State( GLS_DEPTHTEST_DISABLE ); @@ -2008,8 +2059,7 @@ static void RB_RenderSSAO() FBO_Bind(tr.quarterFbo[1]); - qglViewport(0, 0, tr.quarterFbo[1]->width, tr.quarterFbo[1]->height); - qglScissor(0, 0, tr.quarterFbo[1]->width, tr.quarterFbo[1]->height); + GL_SetViewportAndScissor(0, 0, tr.quarterFbo[1]->width, tr.quarterFbo[1]->height); GLSL_BindProgram(&tr.depthBlurShader[0]); @@ -2021,8 +2071,7 @@ static void RB_RenderSSAO() FBO_Bind(tr.screenSsaoFbo); - qglViewport(0, 0, tr.screenSsaoFbo->width, tr.screenSsaoFbo->height); - qglScissor(0, 0, tr.screenSsaoFbo->width, tr.screenSsaoFbo->height); + GL_SetViewportAndScissor(0, 0, tr.screenSsaoFbo->width, tr.screenSsaoFbo->height); GLSL_BindProgram(&tr.depthBlurShader[1]); @@ -2095,7 +2144,7 @@ static void RB_RenderMainPass( drawSurf_t *drawSurfs, int numDrawSurfs ) if (r_drawSun->integer) { - RB_DrawSun(0.1, tr.sunShader); + RB_DrawSun(0.1f, tr.sunShader); } if (r_drawSunRays->integer) @@ -2109,7 +2158,7 @@ static void RB_RenderMainPass( drawSurf_t *drawSurfs, int numDrawSurfs ) tr.sunFlareQueryActive[tr.sunFlareQueryIndex] = qtrue; qglBeginQuery(GL_SAMPLES_PASSED, tr.sunFlareQuery[tr.sunFlareQueryIndex]); - RB_DrawSun(0.3, tr.sunFlareShader); + RB_DrawSun(0.3f, tr.sunFlareShader); qglEndQuery(GL_SAMPLES_PASSED); @@ -2255,6 +2304,12 @@ static void RB_UpdateFogsConstants(gpuFrame_t *frame) fogsBlock.numFogs = tr.world->numfogs - 1; // Don't reserve fog 0 as 'null' } + if (fogsBlock.numFogs > MAX_GPU_FOGS) + { + ri.Printf(PRINT_DEVELOPER, "Too many fogs in current map. Increase MAX_GPU_FOGS\n"); + fogsBlock.numFogs = MAX_GPU_FOGS; + } + for (int i = 0; i < fogsBlock.numFogs; ++i) { const fog_t *fog = tr.world->fogs + i + 1; @@ -2265,7 +2320,25 @@ static void RB_UpdateFogsConstants(gpuFrame_t *frame) fogData->depthToOpaque = sqrtf(-logf(1.0f / 255.0f)) / fog->parms.depthForOpaque; fogData->hasPlane = fog->hasSurface; } +#ifdef REND2_SP + if (tr.refdef.doLAGoggles && fogsBlock.numFogs+1 <= MAX_GPU_FOGS) + { + FogsBlock::Fog *fogData = fogsBlock.fogs + fogsBlock.numFogs; + + vec4_t color = { + 0.75f, + 0.42f + Q_flrand(0.0f, 1.0f) * 0.025f, + 0.07f, + 1.0f + }; + const float depthForOpaque = sqrtf(-logf(1.0f / 255.0f)) / 700.f; + VectorCopy4(color, fogData->color); + fogData->depthToOpaque = depthForOpaque; + fogData->hasPlane = 0; + fogsBlock.numFogs++; + } +#endif tr.fogsUboOffset = RB_AppendConstantsData( frame, &fogsBlock, sizeof(fogsBlock)); } @@ -2293,8 +2366,7 @@ static void RB_UpdateEntityLightConstants( } VectorCopy(lightDir, entityBlock.modelLightDir); - entityBlock.lightOrigin[3] = 0.0f; - entityBlock.lightRadius = lightRadius; + entityBlock.lightOrigin[3] = lightRadius; } static void RB_UpdateEntityMatrixConstants( @@ -2304,7 +2376,6 @@ static void RB_UpdateEntityMatrixConstants( orientationr_t ori; R_RotateForEntity(refEntity, &backEnd.viewParms, &ori); Matrix16Copy(ori.modelMatrix, entityBlock.modelMatrix); - VectorCopy(ori.viewOrigin, entityBlock.localViewOrigin); } static void RB_UpdateEntityModelConstants( @@ -2448,7 +2519,7 @@ static void ComputeDeformValues( void RB_AddShaderToShaderInstanceUBO(shader_t *shader) { - if (shader->numDeforms != 1 && !shader->portalRange) + if (shader->numDeforms != 1 && !shader->portalRange && !shader->timeOffset) { shader->ShaderInstanceUboOffset = -1; return; @@ -2712,7 +2783,7 @@ static const void *RB_SwapBuffers( const void *data ) { long sum = 0; unsigned char *stencilReadback; - stencilReadback = (unsigned char *)ri.Hunk_AllocateTempMemory( glConfig.vidWidth * glConfig.vidHeight ); + stencilReadback = (unsigned char *)Hunk_AllocateTempMemory( glConfig.vidWidth * glConfig.vidHeight ); qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback ); for ( i = 0; i < glConfig.vidWidth * glConfig.vidHeight; i++ ) { @@ -2720,7 +2791,7 @@ static const void *RB_SwapBuffers( const void *data ) { } backEnd.pc.c_overDraw += sum; - ri.Hunk_FreeTempMemory( stencilReadback ); + Hunk_FreeTempMemory( stencilReadback ); } if (!backEnd.framePostProcessed) @@ -2790,7 +2861,7 @@ const void *RB_PostProcess(const void *data) if ( r_dynamicGlow->integer ) { - FBO_FastBlitIndexed(tr.renderFbo, tr.msaaResolveFbo, 1, 1, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); + FBO_FastBlitIndexed(tr.renderFbo, tr.msaaResolveFbo, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST); } } @@ -3055,6 +3126,11 @@ void RB_ExecuteRenderCommands( const void *data ) { case RC_ROTATE_PIC2: data = RB_RotatePic2( data ); break; +#ifdef REND2_SP + case RC_SCISSOR: + data = RB_Scissor(data); + break; +#endif case RC_DRAW_SURFS: data = RB_DrawSurfs( data ); break; diff --git a/codemp/rd-rend2/tr_bsp.cpp b/shared/rd-rend2/tr_bsp.cpp similarity index 96% rename from codemp/rd-rend2/tr_bsp.cpp rename to shared/rd-rend2/tr_bsp.cpp index 172174d318..b519f23ad4 100644 --- a/codemp/rd-rend2/tr_bsp.cpp +++ b/shared/rd-rend2/tr_bsp.cpp @@ -236,7 +236,7 @@ static void R_LoadLightmaps( world_t *worldData, lump_t *l, lump_t *surfs ) { if (externalLightmap != NULL) { tr.worldInternalLightmapping = qfalse; - ri.Hunk_FreeTempMemory(externalLightmap); + Hunk_FreeTempMemory(externalLightmap); } } @@ -299,11 +299,11 @@ static void R_LoadLightmaps( world_t *worldData, lump_t *l, lump_t *surfs ) { tr.numLightmaps = numLightmaps; } - tr.lightmaps = (image_t **)ri.Hunk_Alloc( tr.numLightmaps * sizeof(image_t *), h_low ); + tr.lightmaps = (image_t **)Hunk_Alloc( tr.numLightmaps * sizeof(image_t *), h_low ); if (tr.worldDeluxeMapping) { - tr.deluxemaps = (image_t **)ri.Hunk_Alloc( tr.numLightmaps * sizeof(image_t *), h_low ); + tr.deluxemaps = (image_t **)Hunk_Alloc( tr.numLightmaps * sizeof(image_t *), h_low ); } if (hdr_capable) @@ -444,7 +444,7 @@ static void R_LoadLightmaps( world_t *worldData, lump_t *l, lump_t *surfs ) { color[3] = 1.0f; - R_ColorShiftLightingFloats(color, color, 1.0f / M_PI, false); + R_ColorShiftLightingFloats(color, color, 1.0f, false); ColorToRGBA16F(color, (uint16_t *)(&image[j * 8])); } @@ -631,7 +631,7 @@ static void R_LoadLightmaps( world_t *worldData, lump_t *l, lump_t *surfs ) { if (!tr.deluxemaps) { - tr.deluxemaps = (image_t **)ri.Hunk_Alloc(tr.numLightmaps * sizeof(image_t *), h_low); + tr.deluxemaps = (image_t **)Hunk_Alloc(tr.numLightmaps * sizeof(image_t *), h_low); if (tr.worldInternalLightmapping) { tr.deluxemaps[lightmapnum] = R_CreateImage( @@ -761,7 +761,7 @@ static void R_LoadVisibility( world_t *worldData, lump_t *l ) { byte *buf; len = (worldData->numClusters + 63) & ~63; - worldData->novis = (byte *)ri.Hunk_Alloc(len, h_low); + worldData->novis = (byte *)Hunk_Alloc(len, h_low); Com_Memset(worldData->novis, 0xff, len); len = l->filelen; @@ -780,7 +780,7 @@ static void R_LoadVisibility( world_t *worldData, lump_t *l ) { } else { byte *dest; - dest = (byte *)ri.Hunk_Alloc( len - 8, h_low ); + dest = (byte *)Hunk_Alloc( len - 8, h_low ); Com_Memcpy( dest, buf + 8, len - 8 ); worldData->vis = dest; } @@ -864,15 +864,15 @@ static void ParseFace( const world_t *worldData, dsurface_t *ds, drawVert_t *ver numVerts = LittleLong(ds->numVerts); numIndexes = LittleLong(ds->numIndexes); - //cv = ri.Hunk_Alloc(sizeof(*cv), h_low); + //cv = Hunk_Alloc(sizeof(*cv), h_low); cv = (srfBspSurface_t *)surf->data; cv->surfaceType = SF_FACE; cv->numIndexes = numIndexes; - cv->indexes = (glIndex_t *)ri.Hunk_Alloc(numIndexes * sizeof(cv->indexes[0]), h_low); + cv->indexes = (glIndex_t *)Hunk_Alloc(numIndexes * sizeof(cv->indexes[0]), h_low); cv->numVerts = numVerts; - cv->verts = (srfVert_t *)ri.Hunk_Alloc(numVerts * sizeof(cv->verts[0]), h_low); + cv->verts = (srfVert_t *)Hunk_Alloc(numVerts * sizeof(cv->verts[0]), h_low); // copy vertexes surf->cullinfo.type = CULLINFO_PLANE | CULLINFO_BOX; @@ -914,9 +914,9 @@ static void ParseFace( const world_t *worldData, dsurface_t *ds, drawVert_t *ver if (hdrVertColors) { float *hdrColor = hdrVertColors + (ds->firstVert + i) * 3; - color[0] = hdrColor[0] / M_PI; - color[1] = hdrColor[1] / M_PI; - color[2] = hdrColor[2] / M_PI; + color[0] = hdrColor[0]; + color[1] = hdrColor[1]; + color[2] = hdrColor[2]; scale = 1.0f; } else @@ -1063,9 +1063,9 @@ static void ParseMesh ( const world_t *worldData, dsurface_t *ds, drawVert_t *ve if (hdrVertColors) { float *hdrColor = hdrVertColors + (ds->firstVert + i)*3; - color[0] = hdrColor[0] / M_PI; - color[1] = hdrColor[1] / M_PI; - color[2] = hdrColor[2] / M_PI; + color[0] = hdrColor[0]; + color[1] = hdrColor[1]; + color[2] = hdrColor[2]; scale = 1.0f; } else @@ -1141,15 +1141,15 @@ static void ParseTriSurf( const world_t *worldData, dsurface_t *ds, drawVert_t * numVerts = LittleLong(ds->numVerts); numIndexes = LittleLong(ds->numIndexes); - //cv = ri.Hunk_Alloc(sizeof(*cv), h_low); + //cv = Hunk_Alloc(sizeof(*cv), h_low); cv = (srfBspSurface_t *)surf->data; cv->surfaceType = SF_TRIANGLES; cv->numIndexes = numIndexes; - cv->indexes = (glIndex_t *)ri.Hunk_Alloc(numIndexes * sizeof(cv->indexes[0]), h_low); + cv->indexes = (glIndex_t *)Hunk_Alloc(numIndexes * sizeof(cv->indexes[0]), h_low); cv->numVerts = numVerts; - cv->verts = (srfVert_t *)ri.Hunk_Alloc(numVerts * sizeof(cv->verts[0]), h_low); + cv->verts = (srfVert_t *)Hunk_Alloc(numVerts * sizeof(cv->verts[0]), h_low); surf->data = (surfaceType_t *) cv; @@ -1193,9 +1193,9 @@ static void ParseTriSurf( const world_t *worldData, dsurface_t *ds, drawVert_t * if (hdrVertColors) { float *hdrColor = hdrVertColors + ((ds->firstVert + i) * 3); - color[0] = hdrColor[0] / M_PI; - color[1] = hdrColor[1] / M_PI; - color[2] = hdrColor[2] / M_PI; + color[0] = hdrColor[0]; + color[1] = hdrColor[1]; + color[2] = hdrColor[2]; scale = 1.0f; } else @@ -1274,7 +1274,7 @@ static void ParseFlare( const world_t *worldData, dsurface_t *ds, drawVert_t *ve surf->shader = tr.defaultShader; } - //flare = ri.Hunk_Alloc( sizeof( *flare ), h_low ); + //flare = Hunk_Alloc( sizeof( *flare ), h_low ); flare = (srfFlare_t *)surf->data; flare->surfaceType = SF_FLARE; @@ -1973,21 +1973,21 @@ void R_MovePatchSurfacesToHunk( world_t *worldData ) { continue; // size = sizeof(*grid); - hunkgrid = (srfBspSurface_t *)ri.Hunk_Alloc(size, h_low); + hunkgrid = (srfBspSurface_t *)Hunk_Alloc(size, h_low); Com_Memcpy(hunkgrid, grid, size); - hunkgrid->widthLodError = (float *)ri.Hunk_Alloc( grid->width * 4, h_low ); + hunkgrid->widthLodError = (float *)Hunk_Alloc( grid->width * 4, h_low ); Com_Memcpy( hunkgrid->widthLodError, grid->widthLodError, grid->width * 4 ); - hunkgrid->heightLodError = (float *)ri.Hunk_Alloc( grid->height * 4, h_low ); + hunkgrid->heightLodError = (float *)Hunk_Alloc( grid->height * 4, h_low ); Com_Memcpy( hunkgrid->heightLodError, grid->heightLodError, grid->height * 4 ); hunkgrid->numIndexes = grid->numIndexes; - hunkgrid->indexes = (glIndex_t *)ri.Hunk_Alloc(grid->numIndexes * sizeof(glIndex_t), h_low); + hunkgrid->indexes = (glIndex_t *)Hunk_Alloc(grid->numIndexes * sizeof(glIndex_t), h_low); Com_Memcpy(hunkgrid->indexes, grid->indexes, grid->numIndexes * sizeof(glIndex_t)); hunkgrid->numVerts = grid->numVerts; - hunkgrid->verts = (srfVert_t *)ri.Hunk_Alloc(grid->numVerts * sizeof(srfVert_t), h_low); + hunkgrid->verts = (srfVert_t *)Hunk_Alloc(grid->numVerts * sizeof(srfVert_t), h_low); Com_Memcpy(hunkgrid->verts, grid->verts, grid->numVerts * sizeof(srfVert_t)); R_FreeSurfaceGridMesh( grid ); @@ -2174,8 +2174,8 @@ static void R_CreateWorldVBOs( world_t *worldData ) ri.Printf(PRINT_ALL, "...calculating world VBO %d ( %i verts %i tris )\n", k, numVerts, numIndexes / 3); // create arrays - verts = (packedVertex_t *)ri.Hunk_AllocateTempMemory(numVerts * sizeof(packedVertex_t)); - indexes = (glIndex_t *)ri.Hunk_AllocateTempMemory(numIndexes * sizeof(glIndex_t)); + verts = (packedVertex_t *)Hunk_AllocateTempMemory(numVerts * sizeof(packedVertex_t)); + indexes = (glIndex_t *)Hunk_AllocateTempMemory(numIndexes * sizeof(glIndex_t)); // set up indices and copy vertices numVerts = 0; @@ -2275,8 +2275,8 @@ static void R_CreateWorldVBOs( world_t *worldData ) bspSurf->ibo = ibo; } - ri.Hunk_FreeTempMemory(indexes); - ri.Hunk_FreeTempMemory(verts); + Hunk_FreeTempMemory(indexes); + Hunk_FreeTempMemory(verts); k++; } @@ -2319,13 +2319,13 @@ static void R_LoadSurfaces( world_t *worldData, lump_t *surfs, lump_t *verts, lu if ( indexLump->filelen % sizeof(*indexes)) ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",worldData->name); - out = (msurface_t *)ri.Hunk_Alloc ( count * sizeof(*out), h_low ); + out = (msurface_t *)Hunk_Alloc ( count * sizeof(*out), h_low ); worldData->surfaces = out; worldData->numsurfaces = count; - worldData->surfacesViewCount = (int *)ri.Hunk_Alloc ( count * sizeof(*worldData->surfacesViewCount), h_low ); - worldData->surfacesDlightBits = (int *)ri.Hunk_Alloc ( count * sizeof(*worldData->surfacesDlightBits), h_low ); - worldData->surfacesPshadowBits = (int *)ri.Hunk_Alloc ( count * sizeof(*worldData->surfacesPshadowBits), h_low ); + worldData->surfacesViewCount = (int *)Hunk_Alloc ( count * sizeof(*worldData->surfacesViewCount), h_low ); + worldData->surfacesDlightBits = (int *)Hunk_Alloc ( count * sizeof(*worldData->surfacesDlightBits), h_low ); + worldData->surfacesPshadowBits = (int *)Hunk_Alloc ( count * sizeof(*worldData->surfacesPshadowBits), h_low ); // load hdr vertex colors if (r_hdr->integer) @@ -2372,13 +2372,13 @@ static void R_LoadSurfaces( world_t *worldData, lump_t *surfs, lump_t *verts, lu // FIXME: do this break; case MST_TRIANGLE_SOUP: - out->data = (surfaceType_t *)ri.Hunk_Alloc( sizeof(srfBspSurface_t), h_low); + out->data = (surfaceType_t *)Hunk_Alloc( sizeof(srfBspSurface_t), h_low); break; case MST_PLANAR: - out->data = (surfaceType_t *)ri.Hunk_Alloc( sizeof(srfBspSurface_t), h_low); + out->data = (surfaceType_t *)Hunk_Alloc( sizeof(srfBspSurface_t), h_low); break; case MST_FLARE: - out->data = (surfaceType_t *)ri.Hunk_Alloc( sizeof(srfFlare_t), h_low); + out->data = (surfaceType_t *)Hunk_Alloc( sizeof(srfFlare_t), h_low); break; default: break; @@ -2459,7 +2459,7 @@ static void R_LoadSubmodels( world_t *worldData, int worldIndex, lump_t *l ) { count = l->filelen / sizeof(*in); worldData->numBModels = count; - worldData->bmodels = out = (bmodel_t *)ri.Hunk_Alloc( count * sizeof(*out), h_low ); + worldData->bmodels = out = (bmodel_t *)Hunk_Alloc( count * sizeof(*out), h_low ); for ( i=0 ; idata.bmodel = out; if (worldIndex >= 0) { - Com_sprintf( model->name, sizeof( model->name ), "*%d-%d", worldIndex, i ); + Com_sprintf( model->name, sizeof( model->name ), "*%d-%d", worldIndex+1, i ); } else { @@ -2538,7 +2538,7 @@ static void R_LoadNodesAndLeafs (world_t *worldData, lump_t *nodeLump, lump_t *l numNodes = nodeLump->filelen / sizeof(dnode_t); numLeafs = leafLump->filelen / sizeof(dleaf_t); - out = (mnode_t *)ri.Hunk_Alloc ( (numNodes + numLeafs) * sizeof(*out), h_low); + out = (mnode_t *)Hunk_Alloc ( (numNodes + numLeafs) * sizeof(*out), h_low); worldData->nodes = out; worldData->numnodes = numNodes + numLeafs; @@ -2608,7 +2608,7 @@ static void R_LoadShaders( world_t *worldData, lump_t *l ) { if (l->filelen % sizeof(*in)) ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",worldData->name); count = l->filelen / sizeof(*in); - out = (dshader_t *)ri.Hunk_Alloc ( count*sizeof(*out), h_low ); + out = (dshader_t *)Hunk_Alloc ( count*sizeof(*out), h_low ); worldData->shaders = out; worldData->numShaders = count; @@ -2637,7 +2637,7 @@ static void R_LoadMarksurfaces (world_t *worldData, lump_t *l) if (l->filelen % sizeof(*in)) ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",worldData->name); count = l->filelen / sizeof(*in); - out = (int *)ri.Hunk_Alloc ( count*sizeof(*out), h_low); + out = (int *)Hunk_Alloc ( count*sizeof(*out), h_low); worldData->marksurfaces = out; worldData->nummarksurfaces = count; @@ -2666,7 +2666,8 @@ static void R_LoadPlanes( world_t *worldData, lump_t *l ) { if (l->filelen % sizeof(*in)) ri.Error (ERR_DROP, "LoadMap: funny lump size in %s",worldData->name); count = l->filelen / sizeof(*in); - out = (cplane_t *)ri.Hunk_Alloc ( count*2*sizeof(*out), h_low); + + out = (cplane_t *)Hunk_Alloc ( count*2*sizeof(*out), h_low); worldData->planes = out; worldData->numplanes = count; @@ -2713,7 +2714,7 @@ static void R_LoadFogs( world_t *worldData, lump_t *l, lump_t *brushesLump, lump // create fog strucutres for them worldData->numfogs = count + 1; - worldData->fogs = (fog_t *)ri.Hunk_Alloc ( worldData->numfogs*sizeof(*out), h_low); + worldData->fogs = (fog_t *)Hunk_Alloc ( worldData->numfogs*sizeof(*out), h_low); worldData->globalFog = nullptr; worldData->globalFogIndex = -1; out = worldData->fogs + 1; @@ -2847,7 +2848,7 @@ void R_LoadLightGrid( world_t *worldData, lump_t *l ) { int numGridDataElements = l->filelen / sizeof(*worldData->lightGridData); - worldData->lightGridData = (mgrid_t *)ri.Hunk_Alloc( l->filelen, h_low ); + worldData->lightGridData = (mgrid_t *)Hunk_Alloc( l->filelen, h_low ); Com_Memcpy( worldData->lightGridData, (void *)(fileBase + l->fileofs), l->filelen ); // deal with overbright bits @@ -2883,16 +2884,16 @@ void R_LoadLightGrid( world_t *worldData, lump_t *l ) { ri.Error(ERR_DROP, "Bad size for %s (%i, expected %i)!", filename, size, (int)(sizeof(float)) * 6 * worldData->lightGridBounds[0] * worldData->lightGridBounds[1] * worldData->lightGridBounds[2]); } - worldData->hdrLightGrid = (float *)ri.Hunk_Alloc(size, h_low); + worldData->hdrLightGrid = (float *)Hunk_Alloc(size, h_low); for (i = 0; i < worldData->lightGridBounds[0] * worldData->lightGridBounds[1] * worldData->lightGridBounds[2]; i++) { - worldData->hdrLightGrid[i * 6 ] = hdrLightGrid[i * 6 ] / M_PI; - worldData->hdrLightGrid[i * 6 + 1] = hdrLightGrid[i * 6 + 1] / M_PI; - worldData->hdrLightGrid[i * 6 + 2] = hdrLightGrid[i * 6 + 2] / M_PI; - worldData->hdrLightGrid[i * 6 + 3] = hdrLightGrid[i * 6 + 3] / M_PI; - worldData->hdrLightGrid[i * 6 + 4] = hdrLightGrid[i * 6 + 4] / M_PI; - worldData->hdrLightGrid[i * 6 + 5] = hdrLightGrid[i * 6 + 5] / M_PI; + worldData->hdrLightGrid[i * 6 ] = hdrLightGrid[i * 6 ]; + worldData->hdrLightGrid[i * 6 + 1] = hdrLightGrid[i * 6 + 1]; + worldData->hdrLightGrid[i * 6 + 2] = hdrLightGrid[i * 6 + 2]; + worldData->hdrLightGrid[i * 6 + 3] = hdrLightGrid[i * 6 + 3]; + worldData->hdrLightGrid[i * 6 + 4] = hdrLightGrid[i * 6 + 4]; + worldData->hdrLightGrid[i * 6 + 5] = hdrLightGrid[i * 6 + 5]; } } @@ -2944,10 +2945,13 @@ void R_LoadEntities( world_t *worldData, lump_t *l ) { p = (char *)(fileBase + l->fileofs); // store for reference by the cgame - w->entityString = (char *)ri.Hunk_Alloc( l->filelen + 1, h_low ); + w->entityString = (char *)Hunk_Alloc( l->filelen + 1, h_low ); strcpy( w->entityString, p ); w->entityParsePoint = w->entityString; +#ifdef REND2_SP + COM_BeginParseSession(); +#endif token = COM_ParseExt( &p, qtrue ); if (!*token || *token != '{') { return; @@ -3013,6 +3017,9 @@ void R_LoadEntities( world_t *worldData, lump_t *l ) { continue; } } +#ifdef REND2_SP + COM_EndParseSession(); +#endif } /* @@ -3161,7 +3168,7 @@ void R_LoadEnvironmentJson(const char *baseName) } tr.numCubemaps = JSON_ArrayGetIndex(environmentArrayJson, bufferEnd, NULL, 0); - tr.cubemaps = (cubemap_t *)ri.Hunk_Alloc(tr.numCubemaps * sizeof(*tr.cubemaps), h_low); + tr.cubemaps = (cubemap_t *)Hunk_Alloc(tr.numCubemaps * sizeof(*tr.cubemaps), h_low); for (i = 0; i < tr.numCubemaps; i++) { @@ -3213,7 +3220,7 @@ void R_LoadCubemapEntities(const char *cubemapEntityName) return; tr.numCubemaps = numCubemaps; - tr.cubemaps = (cubemap_t *)ri.Hunk_Alloc(tr.numCubemaps * sizeof(*tr.cubemaps), h_low); + tr.cubemaps = (cubemap_t *)Hunk_Alloc(tr.numCubemaps * sizeof(*tr.cubemaps), h_low); numCubemaps = 0; while(R_ParseSpawnVars(spawnVarChars, sizeof(spawnVarChars), &numSpawnVars, spawnVars)) @@ -3296,12 +3303,6 @@ static void R_RenderAllCubemaps() R_IssuePendingRenderCommands(); R_InitNextFrame(); - GLenum cubemapFormat = GL_RGBA8; - if (r_hdr->integer) - { - cubemapFormat = GL_RGBA16F; - } - for (int k = 0; k <= r_cubeMappingBounces->integer; k++) { bool bounce = k != 0; @@ -3325,7 +3326,7 @@ void R_LoadWeatherZones(world_t *worldData, lump_t *brushesLump, lump_t *sidesLu { dbrush_t *brushes; dbrushside_t *sides; - int brushesCount, sidesCount; + int brushesCount; brushes = (dbrush_t *)(fileBase + brushesLump->fileofs); if (brushesLump->filelen % sizeof(*brushes)) { @@ -3337,7 +3338,6 @@ void R_LoadWeatherZones(world_t *worldData, lump_t *brushesLump, lump_t *sidesLu if (sidesLump->filelen % sizeof(*sides)) { ri.Error(ERR_DROP, "LoadMap: funny lump size in %s", worldData->name); } - sidesCount = sidesLump->filelen / sizeof(*sides); tr.weatherSystem->weatherBrushType = WEATHER_BRUSHES_NONE; @@ -3531,23 +3531,23 @@ static void R_MergeLeafSurfaces(world_t *worldData) // Allocate merged surfaces worldData->mergedSurfaces = - (msurface_t *)ri.Hunk_Alloc( + (msurface_t *)Hunk_Alloc( sizeof(*worldData->mergedSurfaces) * numMergedSurfaces, h_low); worldData->mergedSurfacesViewCount = - (int *)ri.Hunk_Alloc( + (int *)Hunk_Alloc( sizeof(*worldData->mergedSurfacesViewCount) * numMergedSurfaces, h_low); worldData->mergedSurfacesDlightBits = - (int *)ri.Hunk_Alloc( + (int *)Hunk_Alloc( sizeof(*worldData->mergedSurfacesDlightBits) * numMergedSurfaces, h_low); worldData->mergedSurfacesPshadowBits = - (int *)ri.Hunk_Alloc( + (int *)Hunk_Alloc( sizeof(*worldData->mergedSurfacesPshadowBits) * numMergedSurfaces, h_low); worldData->numMergedSurfaces = numMergedSurfaces; // view surfaces are like mark surfaces, except negative ones represent merged surfaces // -1 represents 0, -2 represents 1, and so on worldData->viewSurfaces = - (int *)ri.Hunk_Alloc( + (int *)Hunk_Alloc( sizeof(*worldData->viewSurfaces) * worldData->nummarksurfaces, h_low); // copy view surfaces into mark surfaces @@ -3610,7 +3610,7 @@ static void R_MergeLeafSurfaces(world_t *worldData) } // create ibo - ibo = tr.ibos[tr.numIBOs++] = (IBO_t*)ri.Hunk_Alloc(sizeof(*ibo), h_low); + ibo = tr.ibos[tr.numIBOs++] = (IBO_t*)Hunk_Alloc(sizeof(*ibo), h_low); memset(ibo, 0, sizeof(*ibo)); numIboIndexes = 0; @@ -3642,7 +3642,7 @@ static void R_MergeLeafSurfaces(world_t *worldData) break; } - vboSurf = (srfBspSurface_t *)ri.Hunk_Alloc(sizeof(*vboSurf), h_low); + vboSurf = (srfBspSurface_t *)Hunk_Alloc(sizeof(*vboSurf), h_low); memset(vboSurf, 0, sizeof(*vboSurf)); vboSurf->surfaceType = SF_VBO_MESH; @@ -3823,7 +3823,8 @@ static int R_CreateSurfaceSpritesVertexData( const srfVert_t *verts = bspSurf->verts; const glIndex_t *indexes = bspSurf->indexes; - vec4_t color = { 1.0, 1.0, 1.0, 1.0 }; +#if 0 + vec4_t color = { 1.0f, 1.0f, 1.0f, 1.0f }; if (stage->rgbGen == CGEN_CONST) { color[0] = stage->constantColor[0]; @@ -3835,6 +3836,13 @@ static int R_CreateSurfaceSpritesVertexData( stage->rgbGen == CGEN_EXACT_VERTEX || stage->rgbGen == CGEN_VERTEX_LIT || stage->rgbGen == CGEN_EXACT_VERTEX_LIT); +#else + // Vanilla behaviour is always: color by vertex color of the emitting surface + // even just the blue component used for all three color channels to be exact + // in pseudo code: outVert.rgb = inVert.bbb; + bool vertexLit = true; + vec4_t color = { 1.0f, 1.0f, 1.0f, 1.0f }; +#endif int numSprites = 0; for ( int i = 0, numIndexes = bspSurf->numIndexes; i < numIndexes; i += 3 ) @@ -3967,7 +3975,7 @@ static void R_GenerateSurfaceSprites( out->alphaTestType = stage->alphaTestType; out->numAttributes = 4; - out->attributes = (vertexAttribute_t *)ri.Hunk_Alloc( + out->attributes = (vertexAttribute_t *)Hunk_Alloc( sizeof(vertexAttribute_t) * out->numAttributes, h_low); out->attributes[0].vbo = out->vbo; @@ -4017,7 +4025,7 @@ static void R_GenerateSurfaceSprites( const world_t *world, int worldIndex ) for (int i = 0; i < tr.numShaders; i++) { const shader_t *shader = tr.shaders[i]; - if (shader->spriteUbo != NULL) + if (shader->spriteUbo != 0) continue; numSpriteStages += shader->numSurfaceSpriteStages; @@ -4120,7 +4128,7 @@ static void R_GenerateSurfaceSprites( const world_t *world, int worldIndex ) continue; surf->numSurfaceSprites = shader->numSurfaceSpriteStages; - surf->surfaceSprites = (srfSprites_t *)ri.Hunk_Alloc( + surf->surfaceSprites = (srfSprites_t *)Hunk_Alloc( sizeof(srfSprites_t) * surf->numSurfaceSprites, h_low); int surfaceSpriteNum = 0; @@ -4215,7 +4223,7 @@ world_t *R_LoadBSP(const char *name, int *bspIndex) worldIndex = *bspIndex = tr.numBspModels; - worldData = (world_t *)ri.Hunk_Alloc(sizeof(*worldData), h_low); + worldData = (world_t *)Hunk_Alloc(sizeof(*worldData), h_low); tr.bspModels[tr.numBspModels] = worldData; ++tr.numBspModels; } @@ -4240,7 +4248,7 @@ world_t *R_LoadBSP(const char *name, int *bspIndex) Q_strncpyz(tr.worldName, worldData->name, sizeof(worldData->name)); COM_StripExtension(tr.worldName, tr.worldName, sizeof(tr.worldName)); - const byte *startMarker = (const byte *)ri.Hunk_Alloc(0, h_low); + const byte *startMarker = (const byte *)Hunk_Alloc(0, h_low); dheader_t *header = (dheader_t *)buffer.b; fileBase = (byte *)header; @@ -4295,6 +4303,7 @@ world_t *R_LoadBSP(const char *name, int *bspIndex) &header->lumps[LUMP_BRUSHES], &header->lumps[LUMP_BRUSHSIDES]); + R_LoadWeatherImages(); R_GenerateSurfaceSprites(worldData, worldIndex + 1); // load cubemaps @@ -4317,7 +4326,13 @@ world_t *R_LoadBSP(const char *name, int *bspIndex) { for (int i = 0; i < numCubemapEntities; i++) { +#ifdef REND2_SP + COM_BeginParseSession(); +#endif R_LoadCubemapEntities(cubemapEntities[i]); +#ifdef REND2_SP + COM_EndParseSession(); +#endif if (tr.numCubemaps) break; } @@ -4337,7 +4352,7 @@ world_t *R_LoadBSP(const char *name, int *bspIndex) R_MergeLeafSurfaces(worldData); } - worldData->dataSize = (const byte *)ri.Hunk_Alloc(0, h_low) - startMarker; + worldData->dataSize = (const byte *)Hunk_Alloc(0, h_low) - startMarker; // make sure the VBO glState entries are safe R_BindNullVBO(); @@ -4380,14 +4395,13 @@ void RE_LoadWorldMap( const char *name ) { VectorNormalize(tr.sunDirection); // set default autoexposure settings - tr.autoExposureMinMax[0] = -2.0f; - tr.autoExposureMinMax[1] = 2.0f; + tr.autoExposureMinMax[0] = -3.0f; + tr.autoExposureMinMax[1] = 1.0f; // set default tone mapping settings tr.toneMinAvgMaxLevel[0] = -8.0f; - tr.toneMinAvgMaxLevel[1] = -2.0f; + tr.toneMinAvgMaxLevel[1] = -1.0f; tr.toneMinAvgMaxLevel[2] = 0.0f; - tr.explicitToneMap = false; world_t *world = R_LoadBSP(name); if (world == nullptr) @@ -4398,13 +4412,6 @@ void RE_LoadWorldMap( const char *name ) { return; } - if (r_hdr->integer && tr.hdrLighting && !tr.explicitToneMap) - { - tr.toneMinAvgMaxLevel[0] = -8.0f; - tr.toneMinAvgMaxLevel[1] = 0.0f; - tr.toneMinAvgMaxLevel[2] = 2.0f; - } - tr.worldMapLoaded = qtrue; tr.world = world; diff --git a/codemp/rd-rend2/tr_cache.cpp b/shared/rd-rend2/tr_cache.cpp similarity index 96% rename from codemp/rd-rend2/tr_cache.cpp rename to shared/rd-rend2/tr_cache.cpp index 0e5d5a2b99..a1d89de26f 100644 --- a/codemp/rd-rend2/tr_cache.cpp +++ b/shared/rd-rend2/tr_cache.cpp @@ -81,7 +81,7 @@ qboolean CModelCacheManager::LoadFile( const char *pFileName, void **ppFileBuffe if (!strcmp (sDEFAULT_GLA_NAME ".gla", path)) { // return fake params as though it was found on disk... - void *pvFakeGLAFile = Z_Malloc(sizeof (FakeGLAFile), TAG_FILESYS, qfalse); + void *pvFakeGLAFile = R_Malloc(sizeof (FakeGLAFile), TAG_FILESYS, qfalse); memcpy(pvFakeGLAFile, &FakeGLAFile[0], sizeof (FakeGLAFile)); *ppFileBuffer = pvFakeGLAFile; @@ -103,7 +103,7 @@ qboolean CModelCacheManager::LoadFile( const char *pFileName, void **ppFileBuffe void* CModelCacheManager::Allocate( int iSize, void *pvDiskBuffer, const char *psModelFileName, qboolean *bAlreadyFound, memtag_t eTag ) { - int iChecksum; + int iChecksum = 1; char sModelName[MAX_QPATH]; /* Standard NULL checking. */ @@ -124,16 +124,20 @@ void* CModelCacheManager::Allocate( int iSize, void *pvDiskBuffer, const char *p if( pvDiskBuffer ) Z_MorphMallocTag( pvDiskBuffer, eTag ); else - pvDiskBuffer = Z_Malloc(iSize, eTag, qfalse); + pvDiskBuffer = R_Malloc(iSize, eTag, qfalse); files.emplace_back(); pFile = &files.back(); pFile->pDiskImage = pvDiskBuffer; pFile->iAllocSize = iSize; Q_strncpyz(pFile->path, sModelName, sizeof(pFile->path)); - +#ifndef REND2_SP if( ri.FS_FileIsInPAK( sModelName, &iChecksum ) ) pFile->iPAKChecksum = iChecksum; /* Otherwise, it will be -1. */ +#else + if (ri.FS_FileIsInPAK(sModelName)) + pFile->iPAKChecksum = iChecksum; /* Otherwise, it will be -1. */ +#endif *bAlreadyFound = qfalse; } @@ -177,7 +181,12 @@ void CModelCacheManager::DumpNonPure( void ) for ( auto it = files.begin(); it != files.end(); /* empty */ ) { int iChecksum; +#ifndef REND2_SP int iInPak = ri.FS_FileIsInPAK( it->path, &iChecksum ); +#else + int iInPak = ri.FS_FileIsInPAK(it->path); + iChecksum = it->iPAKChecksum; +#endif if( iInPak == -1 || iChecksum != it->iPAKChecksum ) { diff --git a/codemp/rd-rend2/tr_cache.h b/shared/rd-rend2/tr_cache.h similarity index 100% rename from codemp/rd-rend2/tr_cache.h rename to shared/rd-rend2/tr_cache.h diff --git a/codemp/rd-rend2/tr_cmds.cpp b/shared/rd-rend2/tr_cmds.cpp similarity index 96% rename from codemp/rd-rend2/tr_cmds.cpp rename to shared/rd-rend2/tr_cmds.cpp index e29d63ee02..47adf297b6 100644 --- a/codemp/rd-rend2/tr_cmds.cpp +++ b/shared/rd-rend2/tr_cmds.cpp @@ -487,6 +487,33 @@ void R_SetColorMode(GLboolean *rgba, stereoFrame_t stereoFrame, int colormode) } } +#ifdef REND2_SP +void RE_LAGoggles(void) +{ + tr.refdef.doLAGoggles = true; + tr.refdef.doFullbright = true; +} + +/* +============= +RE_Scissor +============= +*/ +void RE_Scissor(float x, float y, float w, float h) +{ + scissorCommand_t* cmd; + + cmd = (scissorCommand_t*)R_GetCommandBuffer(sizeof(*cmd)); + if (!cmd) { + return; + } + cmd->commandId = RC_SCISSOR; + cmd->x = x; + cmd->y = y; + cmd->w = w; + cmd->h = h; +} +#endif /* ==================== @@ -525,7 +552,10 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) { qglDeleteSync( sync ); thisFrame->sync = NULL; - thisFrame->uboWriteOffset = 0; + for (byte i = 0; i < MAX_SCENES; i++) + { + thisFrame->uboWriteOffset[i] = 0; + } thisFrame->dynamicIboCommitOffset = 0; thisFrame->dynamicIboWriteOffset = 0; @@ -549,9 +579,12 @@ void RE_BeginFrame( stereoFrame_t stereoFrame ) { R_SaveScreenshot(&thisFrame->screenshotReadback); // Resets resources - qglBindBuffer(GL_UNIFORM_BUFFER, thisFrame->ubo); - glState.currentGlobalUBO = thisFrame->ubo; - thisFrame->uboWriteOffset = 0; + for (byte i = 0; i < MAX_SCENES; i++) + { + qglBindBuffer(GL_UNIFORM_BUFFER, thisFrame->ubo[i]); + glState.currentGlobalUBO = thisFrame->ubo[i]; + thisFrame->uboWriteOffset[i] = 0; + } thisFrame->dynamicIboCommitOffset = 0; thisFrame->dynamicIboWriteOffset = 0; @@ -753,6 +786,7 @@ void R_NewFrameSync() assert(!currentFrame->sync); currentFrame->sync = qglFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + currentFrame->currentScene = 0; backEndData->realFrameNumber++; backEnd.framePostProcessed = qfalse; diff --git a/codemp/rd-rend2/tr_curve.cpp b/shared/rd-rend2/tr_curve.cpp similarity index 98% rename from codemp/rd-rend2/tr_curve.cpp rename to shared/rd-rend2/tr_curve.cpp index 90c24c4950..4a966d7e9b 100644 --- a/codemp/rd-rend2/tr_curve.cpp +++ b/shared/rd-rend2/tr_curve.cpp @@ -386,21 +386,23 @@ srfBspSurface_t *R_CreateSurfaceGridMesh(int width, int height, // copy the results out to a grid size = (width * height - 1) * sizeof( srfVert_t ) + sizeof( *grid ); - grid = /*ri.Hunk_Alloc*/ (srfBspSurface_t *)Z_Malloc( size, TAG_GRIDMESH ); + grid = /*ri.Hunk_Alloc*/ (srfBspSurface_t *)R_Malloc( size, TAG_GRIDMESH ); + Com_Memset(grid, 0, size); - grid->widthLodError = /*ri.Hunk_Alloc*/ (float *)Z_Malloc( width * 4, TAG_GRIDMESH ); + grid->widthLodError = /*ri.Hunk_Alloc*/ (float *)R_Malloc( width * 4, TAG_GRIDMESH ); Com_Memcpy( grid->widthLodError, errorTable[0], width * 4 ); - grid->heightLodError = /*ri.Hunk_Alloc*/ (float *)Z_Malloc( height * 4, TAG_GRIDMESH ); + grid->heightLodError = /*ri.Hunk_Alloc*/ (float *)R_Malloc( height * 4, TAG_GRIDMESH ); Com_Memcpy( grid->heightLodError, errorTable[1], height * 4 ); grid->numIndexes = numIndexes; - grid->indexes = (glIndex_t *)Z_Malloc(grid->numIndexes * sizeof(glIndex_t), TAG_GRIDMESH); + grid->indexes = (glIndex_t *)R_Malloc(grid->numIndexes * sizeof(glIndex_t), TAG_GRIDMESH); Com_Memcpy(grid->indexes, indexes, numIndexes * sizeof(glIndex_t)); grid->numVerts = (width * height); - grid->verts = (srfVert_t *)Z_Malloc(grid->numVerts * sizeof(srfVert_t), TAG_GRIDMESH); + + grid->verts = (srfVert_t *)R_Malloc(grid->numVerts * sizeof(srfVert_t), TAG_GRIDMESH); grid->width = width; grid->height = height; diff --git a/codemp/rd-rend2/tr_decals.cpp b/shared/rd-rend2/tr_decals.cpp similarity index 97% rename from codemp/rd-rend2/tr_decals.cpp rename to shared/rd-rend2/tr_decals.cpp index 5a1c98d087..87fd5e3097 100644 --- a/codemp/rd-rend2/tr_decals.cpp +++ b/shared/rd-rend2/tr_decals.cpp @@ -209,7 +209,7 @@ void RE_AddDecalToScene( qhandle_t decalShader, const vec3_t origin, const vec3_ // if it is a temporary (shadow) mark, add it immediately and forget about it if ( temporary ) { - RE_AddPolyToScene( decalShader, mf->numPoints, verts, 1 ); + RE_AddPolyToScene( decalShader, mf->numPoints, verts ); continue; } @@ -275,7 +275,7 @@ void R_AddDecals( void ) p->verts[j].modulate[3] = fade; } - RE_AddPolyToScene( p->shader, p->poly.numVerts, p->verts, 1 ); + RE_AddPolyToScene( p->shader, p->poly.numVerts, p->verts ); } else { @@ -284,7 +284,7 @@ void R_AddDecals( void ) } else { - RE_AddPolyToScene( p->shader, p->poly.numVerts, p->verts, 1 ); + RE_AddPolyToScene( p->shader, p->poly.numVerts, p->verts ); } } diff --git a/codemp/rd-rend2/tr_extensions.cpp b/shared/rd-rend2/tr_extensions.cpp similarity index 99% rename from codemp/rd-rend2/tr_extensions.cpp rename to shared/rd-rend2/tr_extensions.cpp index 83190a3425..b02f0b45b4 100644 --- a/codemp/rd-rend2/tr_extensions.cpp +++ b/shared/rd-rend2/tr_extensions.cpp @@ -215,6 +215,7 @@ PFNGLGETQUERYOBJECTUIVPROC qglGetQueryObjectuiv; // GL state PFNGLGETSTRINGIPROC qglGetStringi; +PFNGLCOLORMASKIPROC qglColorMaski; // Sync objects and fences PFNGLFENCESYNCPROC qglFenceSync; @@ -512,6 +513,7 @@ void GLimp_InitCoreFunctions() // GL state GetGLFunction (qglGetStringi, "glGetStringi", qtrue); + GetGLFunction (qglColorMaski, "glColorMaski", qtrue); // Sync objects and fences GetGLFunction (qglFenceSync, "glFenceSync", qtrue); diff --git a/codemp/rd-rend2/tr_extramath.cpp b/shared/rd-rend2/tr_extramath.cpp similarity index 100% rename from codemp/rd-rend2/tr_extramath.cpp rename to shared/rd-rend2/tr_extramath.cpp diff --git a/codemp/rd-rend2/tr_extramath.h b/shared/rd-rend2/tr_extramath.h similarity index 100% rename from codemp/rd-rend2/tr_extramath.h rename to shared/rd-rend2/tr_extramath.h diff --git a/codemp/rd-rend2/tr_extratypes.h b/shared/rd-rend2/tr_extratypes.h similarity index 100% rename from codemp/rd-rend2/tr_extratypes.h rename to shared/rd-rend2/tr_extratypes.h diff --git a/codemp/rd-rend2/tr_fbo.cpp b/shared/rd-rend2/tr_fbo.cpp similarity index 99% rename from codemp/rd-rend2/tr_fbo.cpp rename to shared/rd-rend2/tr_fbo.cpp index d86085412d..0b5a95f7be 100644 --- a/codemp/rd-rend2/tr_fbo.cpp +++ b/shared/rd-rend2/tr_fbo.cpp @@ -123,7 +123,7 @@ FBO_t *FBO_Create(const char *name, int width, int height) ri.Error(ERR_DROP, "FBO_Create: MAX_FBOS hit"); } - fbo = tr.fbos[tr.numFBOs] = (FBO_t *)ri.Hunk_Alloc(sizeof(*fbo), h_low); + fbo = tr.fbos[tr.numFBOs] = (FBO_t *)Hunk_Alloc(sizeof(*fbo), h_low); Q_strncpyz(fbo->name, name, sizeof(fbo->name)); fbo->index = tr.numFBOs++; fbo->width = width; @@ -819,8 +819,7 @@ void FBO_BlitFromTexture(struct image_s *src, vec4i_t inSrcBox, vec2_t inSrcTexS height = glConfig.vidHeight; } - qglViewport( 0, 0, width, height ); - qglScissor( 0, 0, width, height ); + GL_SetViewportAndScissor(0, 0, width, height); Matrix16Ortho(0, width, height, 0, 0, 1, projection); diff --git a/codemp/rd-rend2/tr_fbo.h b/shared/rd-rend2/tr_fbo.h similarity index 100% rename from codemp/rd-rend2/tr_fbo.h rename to shared/rd-rend2/tr_fbo.h diff --git a/codemp/rd-rend2/tr_flares.cpp b/shared/rd-rend2/tr_flares.cpp similarity index 100% rename from codemp/rd-rend2/tr_flares.cpp rename to shared/rd-rend2/tr_flares.cpp diff --git a/codemp/rd-rend2/tr_ghoul2.cpp b/shared/rd-rend2/tr_ghoul2.cpp similarity index 96% rename from codemp/rd-rend2/tr_ghoul2.cpp rename to shared/rd-rend2/tr_ghoul2.cpp index 97fa30cad6..bf9589e3e4 100644 --- a/codemp/rd-rend2/tr_ghoul2.cpp +++ b/shared/rd-rend2/tr_ghoul2.cpp @@ -3,7 +3,9 @@ #include "qcommon/matcomp.h" #include "qcommon/qcommon.h" #include "ghoul2/G2.h" +#ifndef REND2_SP #include "ghoul2/g2_local.h" +#endif // !REND2_SP #ifdef _G2_GORE #include "G2_gore_r2.h" #endif @@ -11,7 +13,9 @@ #ifdef _MSC_VER #pragma warning (disable: 4512) //default assignment operator could not be gened #endif +#ifndef REND2_SP #include "qcommon/disablewarnings.h" +#endif // !REND2_SP #include "tr_cache.h" #define LL(x) x=LittleLong(x) @@ -81,6 +85,10 @@ void G2Time_ReportTimers(void) //rww - RAGDOLL_END +#ifdef REND2_SP +extern cvar_t* sv_mapname; +#endif + static const int MAX_RENDERABLE_SURFACES = 2048; static CRenderableSurface renderSurfHeap[MAX_RENDERABLE_SURFACES]; static int currentRenderSurfIndex = 0; @@ -917,20 +925,26 @@ R_AComputeFogNum */ static int R_GComputeFogNum( trRefEntity_t *ent ) { - int i, j; + int i; + float frameRadius; fog_t *fog; + vec3_t localOrigin; if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) { return 0; } + VectorCopy(ent->e.origin, localOrigin); + frameRadius = ent->e.radius; +#ifndef REND2_SP + int j; for ( i = 1 ; i < tr.world->numfogs ; i++ ) { fog = &tr.world->fogs[i]; for ( j = 0 ; j < 3 ; j++ ) { - if ( ent->e.origin[j] - ent->e.radius >= fog->bounds[1][j] ) { + if ( localOrigin[j] - frameRadius >= fog->bounds[1][j] ) { break; } - if ( ent->e.origin[j] + ent->e.radius <= fog->bounds[0][j] ) { + if ( localOrigin[j] + frameRadius <= fog->bounds[0][j] ) { break; } } @@ -938,8 +952,40 @@ static int R_GComputeFogNum( trRefEntity_t *ent ) { return i; } } - return 0; +#else + int partialFog = 0; + for (i = 1; i < tr.world->numfogs; i++) { + fog = &tr.world->fogs[i]; + if (localOrigin[0] - frameRadius >= fog->bounds[0][0] + && localOrigin[0] + frameRadius <= fog->bounds[1][0] + && localOrigin[1] - frameRadius >= fog->bounds[0][1] + && localOrigin[1] + frameRadius <= fog->bounds[1][1] + && localOrigin[2] - frameRadius >= fog->bounds[0][2] + && localOrigin[2] + frameRadius <= fog->bounds[1][2]) + {//totally inside it + return i; + break; + } + if ((localOrigin[0] - frameRadius >= fog->bounds[0][0] && localOrigin[1] - frameRadius >= fog->bounds[0][1] && localOrigin[2] - frameRadius >= fog->bounds[0][2] && + localOrigin[0] - frameRadius <= fog->bounds[1][0] && localOrigin[1] - frameRadius <= fog->bounds[1][1] && localOrigin[2] - frameRadius <= fog->bounds[1][2]) || + (localOrigin[0] + frameRadius >= fog->bounds[0][0] && localOrigin[1] + frameRadius >= fog->bounds[0][1] && localOrigin[2] + frameRadius >= fog->bounds[0][2] && + localOrigin[0] + frameRadius <= fog->bounds[1][0] && localOrigin[1] + frameRadius <= fog->bounds[1][1] && localOrigin[2] + frameRadius <= fog->bounds[1][2])) + {//partially inside it + //if (tr.refdef.fogIndex == i || R_FogParmsMatch(tr.refdef.fogIndex, i)) + //{//take new one only if it's the same one that the viewpoint is in + // return i; + // break; + //} + //else + if (!partialFog) + {//first partialFog + partialFog = i; + } + } + } + return partialFog; +#endif } // work out lod for this entity. @@ -1870,6 +1916,7 @@ static void G2_TransformBone( int child, CBoneCache& BC ) } } +/* void G2_SetUpBolts( mdxaHeader_t *header, CGhoul2Info &ghoul2, @@ -1892,6 +1939,7 @@ void G2_SetUpBolts( boltList[i].position = bonePtr[boltList[i].boneNumber].second * skel->BasePoseMat; } } +*/ #define GHOUL2_RAG_STARTED 0x0010 //rwwFIXMEFIXME: Move this into the stupid header or something. @@ -1943,11 +1991,14 @@ static void G2_TransformGhoulBones( float val = r_Ghoul2AnimSmooth->value; if (val > 0.0f && val < 1.0f) { +#ifndef REND2_SP if (ghoul2.mFlags & GHOUL2_CRAZY_SMOOTH) { val = 0.9f; } - else if (ghoul2.mFlags & GHOUL2_RAG_STARTED) + else +#endif + if (ghoul2.mFlags & GHOUL2_RAG_STARTED) { for (size_t k = 0; k < rootBoneList.size(); k++) { @@ -2026,7 +2077,7 @@ static void G2_TransformGhoulBones( // // Surface Manipulation code - +#ifndef REND2_SP // We've come across a surface that's designated as a bolt surface, process it and put it in the appropriate bolt place void G2_ProcessSurfaceBolt( mdxaBone_v &bonePtr, @@ -2319,6 +2370,7 @@ void G2_ProcessGeneratedSurfaceBolts(CGhoul2Info &ghoul2, mdxaBone_v &bonePtr, m G2PerformanceTimer_G2_ProcessGeneratedSurfaceBolts.End(); #endif } +#endif void RenderSurfaces( CRenderSurface &RS, const trRefEntity_t *ent, int entityNum ) { @@ -2367,7 +2419,7 @@ void RenderSurfaces( CRenderSurface &RS, const trRefEntity_t *ent, int entityNum int j; // match the surface name to something in the skin file - shader = tr.defaultShader; + shader = R_GetShaderByHandle(surfInfo->shaderIndex); for ( j = 0 ; j < RS.skin->numSurfaces ; j++ ) { // the names have both been lowercased @@ -2454,7 +2506,7 @@ void RenderSurfaces( CRenderSurface &RS, const trRefEntity_t *ent, int entityNum float(curTime - kcur->second.mGoreGrowStartTime) / float(magicFactor42); // linear } -#ifdef REND2_SP_MAYBE +#ifdef REND2_SP_GORE if (curTime < kcur->second.mGoreGrowEndTime) { newSurf2->scale = Q_max( @@ -2474,7 +2526,7 @@ void RenderSurfaces( CRenderSurface &RS, const trRefEntity_t *ent, int entityNum { gshader = R_GetShaderByHandle(goreShader); } -#ifdef REND2_SP_MAYBE +#ifdef REND2_SP_GORE // Set fade on surf. // Only if we have a fade time set, and let us fade on // rgb if we want -rww @@ -2543,6 +2595,7 @@ void RenderSurfaces( CRenderSurface &RS, const trRefEntity_t *ent, int entityNum #endif } +/* // Go through the model and deal with just the surfaces that are tagged as bolt // on points - this is for the server side skeleton construction void ProcessModelBoltSurfaces( @@ -2608,7 +2661,7 @@ void ProcessModelBoltSurfaces( G2Time_ProcessModelBoltSurfaces += G2PerformanceTimer_ProcessModelBoltSurfaces.End(); #endif } - +*/ // build the used bone list so when doing bone transforms we can determine if we need to do it or not void G2_ConstructUsedBoneList(CConstructBoneList &CBL) @@ -2618,7 +2671,11 @@ void G2_ConstructUsedBoneList(CConstructBoneList &CBL) mdxmHeader_t *mdxm = CBL.currentModel->data.glm->header; // back track and get the surfinfo struct for this surface +#ifndef REND2_SP const mdxmSurface_t *surface = (mdxmSurface_t *)G2_FindSurface((void *)CBL.currentModel, CBL.surfaceNum, 0); +#else + const mdxmSurface_t *surface = (mdxmSurface_t *)G2_FindSurface(CBL.currentModel, CBL.surfaceNum, 0); +#endif const mdxmHierarchyOffsets_t *surfIndexes = (mdxmHierarchyOffsets_t *)((byte *)mdxm + sizeof(mdxmHeader_t)); const mdxmSurfHierarchy_t *surfInfo = (mdxmSurfHierarchy_t *)((byte *)surfIndexes + surfIndexes->offsets[surface->thisSurfaceIndex]); const model_t *mod_a = R_GetModelByHandle(mdxm->animIndex); @@ -3232,19 +3289,22 @@ void R_AddGhoulSurfaces( trRefEntity_t *ent, int entityNum ) else { cust_shader = nullptr; +#ifndef REND2_SP // figure out the custom skin thing if (g2Info.mCustomSkin) { - skin = R_GetSkinByHandle(g2Info.mCustomSkin ); - } - else if (ent->e.customSkin) - { - skin = R_GetSkinByHandle(ent->e.customSkin ); - } - else if ( g2Info.mSkin > 0 && g2Info.mSkin < tr.numSkins ) - { - skin = R_GetSkinByHandle( g2Info.mSkin ); + skin = R_GetSkinByHandle(g2Info.mCustomSkin); } + else +#endif + if (ent->e.customSkin) + { + skin = R_GetSkinByHandle(ent->e.customSkin); + } + else if (g2Info.mSkin > 0 && g2Info.mSkin < tr.numSkins) + { + skin = R_GetSkinByHandle(g2Info.mSkin); + } } int whichLod = G2_ComputeLOD( ent, g2Info.currentModel, g2Info.mLodBias ); @@ -3494,7 +3554,11 @@ void RB_TransformBones(const trRefEntity_t *ent, const trRefdef_t *refdef, int c for (int bone = 0; bone < (int)bc->mBones.size(); bone++) { +#ifdef JK2_MODE + const mdxaBone_t& b = bc->Eval(bone); +#else const mdxaBone_t& b = bc->EvalRender(bone); +#endif // JK2_MODE Com_Memcpy( bc->boneMatrices + bone, &b.matrix[0][0], @@ -3566,7 +3630,7 @@ void RB_SurfaceGhoul( CRenderableSurface *surf ) maxIndex = surf->alternateTex->firstVert + surf->alternateTex->numVerts; indexOffset = surf->alternateTex->firstIndex; -#ifdef REND2_SP_MAYBE +#ifdef REND2_SP_GORE // UNTESTED CODE if (surf->scale > 1.0f) { @@ -3600,8 +3664,6 @@ void RB_SurfaceGhoul( CRenderableSurface *surf ) tess.svars.colors[tess.firstIndex][3] = lFade; } } - tess.scale = false; - tess.fade = false; #endif } else { #endif @@ -4097,7 +4159,7 @@ qboolean R_LoadMDXM(model_t *mod, void *buffer, const char *mod_name, qboolean & qboolean bAlreadyFound = qfalse; mdxm = (mdxmHeader_t*)CModelCache->Allocate(size, buffer, mod_name, &bAlreadyFound, TAG_MODEL_GLM); - mod->data.glm = (mdxmData_t *)ri.Hunk_Alloc (sizeof (mdxmData_t), h_low); + mod->data.glm = (mdxmData_t *)Hunk_Alloc(sizeof (mdxmData_t), h_low); mod->data.glm->header = mdxm; //RE_RegisterModels_Malloc(size, buffer, mod_name, &bAlreadyFound, TAG_MODEL_GLM); @@ -4125,9 +4187,42 @@ qboolean R_LoadMDXM(model_t *mod, void *buffer, const char *mod_name, qboolean & LL(mdxm->ofsEnd); } + if (mdxm->numBones > MAX_G2_BONES) + { + Com_Printf(S_COLOR_YELLOW "R_LoadMDXM: model %s has too many bones for rend2\n", mdxm->name); + return qfalse; + } + // first up, go load in the animation file we need that has the skeletal // animation info for this model - mdxm->animIndex = RE_RegisterModel(va ("%s.gla",mdxm->animName)); + mdxm->animIndex = RE_RegisterModel(va("%s.gla", mdxm->animName)); +#ifdef REND2_SP + char animGLAName[MAX_QPATH]; + char* strippedName; + char* slash = NULL; + const char* mapname = sv_mapname->string; + + if (strcmp(mapname, "nomap")) + { + if (strrchr(mapname, '/')) //maps in subfolders use the root name, ( presuming only one level deep!) + { + mapname = strrchr(mapname, '/') + 1; + } + //stripped name of GLA for this model + Q_strncpyz(animGLAName, mdxm->animName, sizeof(animGLAName)); + slash = strrchr(animGLAName, '/'); + if (slash) + { + *slash = 0; + } + strippedName = COM_SkipPath(animGLAName); + if (VALIDSTRING(strippedName)) + { + RE_RegisterModel(va("models/players/%s_%s/%s_%s.gla", strippedName, mapname, strippedName, mapname)); + } + } + +#endif if (!mdxm->animIndex) { @@ -4137,28 +4232,30 @@ qboolean R_LoadMDXM(model_t *mod, void *buffer, const char *mod_name, qboolean & mod->numLods = mdxm->numLODs -1 ; //copy this up to the model for ease of use - it wil get inced after this. - if (bAlreadyFound) - { - return qtrue; // All done. Stop, go no further, do not LittleLong(), do not pass Go... - } - +#ifndef JK2_MODE bool isAnOldModelFile = false; if (mdxm->numBones == 72 && strstr(mdxm->animName,"_humanoid") ) { isAnOldModelFile = true; } - +#endif surfInfo = (mdxmSurfHierarchy_t *)( (byte *)mdxm + mdxm->ofsSurfHierarchy); for ( i = 0 ; i < mdxm->numSurfaces ; i++) { LL(surfInfo->numChildren); LL(surfInfo->parentIndex); - +#ifndef JK2_MODE Q_strlwr(surfInfo->name); //just in case if ( !strcmp( &surfInfo->name[strlen(surfInfo->name)-4],"_off") ) { surfInfo->name[strlen(surfInfo->name)-4]=0; //remove "_off" from name } +#endif + + if (surfInfo->shader[0] == '[') + { + surfInfo->shader[0] = 0; //kill the stupid [nomaterial] since carcass doesn't + } // do all the children indexs for (j=0; jnumChildren; j++) @@ -4228,7 +4325,7 @@ qboolean R_LoadMDXM(model_t *mod, void *buffer, const char *mod_name, qboolean & // change to surface identifier surf->ident = SF_MDX; // register the shaders - +#ifndef JK2_MODE if (isAnOldModelFile) { int *boneRef = (int *) ( (byte *)surf + surf->ofsBoneReferences ); @@ -4244,6 +4341,7 @@ qboolean R_LoadMDXM(model_t *mod, void *buffer, const char *mod_name, qboolean & } } } +#endif // find the next surface surf = (mdxmSurface_t *)( (byte *)surf + surf->ofsEnd ); } @@ -4254,7 +4352,7 @@ qboolean R_LoadMDXM(model_t *mod, void *buffer, const char *mod_name, qboolean & // Make a copy on the GPU lod = (mdxmLOD_t *)((byte *)mdxm + mdxm->ofsLODs); - mod->data.glm->vboModels = (mdxmVBOModel_t *)ri.Hunk_Alloc (sizeof (mdxmVBOModel_t) * mdxm->numLODs, h_low); + mod->data.glm->vboModels = (mdxmVBOModel_t *)Hunk_Alloc (sizeof (mdxmVBOModel_t) * mdxm->numLODs, h_low); for ( l = 0; l < mdxm->numLODs; l++ ) { mdxmVBOModel_t *vboModel = &mod->data.glm->vboModels[l]; @@ -4275,11 +4373,11 @@ qboolean R_LoadMDXM(model_t *mod, void *buffer, const char *mod_name, qboolean & int numTriangles = 0; // +1 to add total vertex count - int *baseVertexes = (int *)ri.Hunk_AllocateTempMemory (sizeof (int) * (mdxm->numSurfaces + 1)); - int *indexOffsets = (int *)ri.Hunk_AllocateTempMemory (sizeof (int) * mdxm->numSurfaces); + int *baseVertexes = (int *)Hunk_AllocateTempMemory (sizeof (int) * (mdxm->numSurfaces + 1)); + int *indexOffsets = (int *)Hunk_AllocateTempMemory (sizeof (int) * mdxm->numSurfaces); vboModel->numVBOMeshes = mdxm->numSurfaces; - vboModel->vboMeshes = (mdxmVBOMesh_t *)ri.Hunk_Alloc (sizeof (mdxmVBOMesh_t) * mdxm->numSurfaces, h_low); + vboModel->vboMeshes = (mdxmVBOMesh_t *)Hunk_Alloc (sizeof (mdxmVBOMesh_t) * mdxm->numSurfaces, h_low); vboMeshes = vboModel->vboMeshes; surf = (mdxmSurface_t *)((byte *)lod + sizeof (mdxmLOD_t) + (mdxm->numSurfaces * sizeof (mdxmLODSurfOffset_t))); @@ -4306,7 +4404,7 @@ qboolean R_LoadMDXM(model_t *mod, void *buffer, const char *mod_name, qboolean & dataSize += numVerts * sizeof (*tangents); // Allocate and write to memory - data = (byte *)ri.Hunk_AllocateTempMemory (dataSize); + data = (byte *)Hunk_AllocateTempMemory (dataSize); ofsPosition = stride; verts = (vec3_t *)(data + ofsPosition); @@ -4333,16 +4431,16 @@ qboolean R_LoadMDXM(model_t *mod, void *buffer, const char *mod_name, qboolean & stride += sizeof (*tangents); // Fill in the index buffer and compute tangents - glIndex_t *indices = (glIndex_t *)ri.Hunk_AllocateTempMemory(sizeof(glIndex_t) * numTriangles * 3); + glIndex_t *indices = (glIndex_t *)Hunk_AllocateTempMemory(sizeof(glIndex_t) * numTriangles * 3); glIndex_t *index = indices; - uint32_t *tangentsf = (uint32_t *)ri.Hunk_AllocateTempMemory(sizeof(uint32_t) * numVerts); + uint32_t *tangentsf = (uint32_t *)Hunk_AllocateTempMemory(sizeof(uint32_t) * numVerts); surf = (mdxmSurface_t *)((byte *)lod + sizeof(mdxmLOD_t) + (mdxm->numSurfaces * sizeof(mdxmLODSurfOffset_t))); for (int n = 0; n < mdxm->numSurfaces; n++) { mdxmTriangle_t *t = (mdxmTriangle_t *)((byte *)surf + surf->ofsTriangles); - glIndex_t *surf_indices = (glIndex_t *)ri.Hunk_AllocateTempMemory(sizeof(glIndex_t) * surf->numTriangles * 3); + glIndex_t *surf_indices = (glIndex_t *)Hunk_AllocateTempMemory(sizeof(glIndex_t) * surf->numTriangles * 3); glIndex_t *surf_index = surf_indices; for (int k = 0; k < surf->numTriangles; k++, index += 3, surf_index += 3) @@ -4373,7 +4471,7 @@ qboolean R_LoadMDXM(model_t *mod, void *buffer, const char *mod_name, qboolean & surf_indices ); - ri.Hunk_FreeTempMemory(surf_indices); + Hunk_FreeTempMemory(surf_indices); surf = (mdxmSurface_t *)((byte *)surf + surf->ofsEnd); } @@ -4460,9 +4558,9 @@ qboolean R_LoadMDXM(model_t *mod, void *buffer, const char *mod_name, qboolean & VBO_t *vbo = R_CreateVBO (data, dataSize, VBO_USAGE_STATIC); IBO_t *ibo = R_CreateIBO((byte *)indices, sizeof(glIndex_t) * numTriangles * 3, VBO_USAGE_STATIC); - ri.Hunk_FreeTempMemory (data); - ri.Hunk_FreeTempMemory (tangentsf); - ri.Hunk_FreeTempMemory (indices); + Hunk_FreeTempMemory (data); + Hunk_FreeTempMemory (tangentsf); + Hunk_FreeTempMemory (indices); vbo->offsets[ATTR_INDEX_POSITION] = ofsPosition; vbo->offsets[ATTR_INDEX_NORMAL] = ofsNormals; @@ -4504,8 +4602,8 @@ qboolean R_LoadMDXM(model_t *mod, void *buffer, const char *mod_name, qboolean & vboModel->vbo = vbo; vboModel->ibo = ibo; - ri.Hunk_FreeTempMemory (indexOffsets); - ri.Hunk_FreeTempMemory (baseVertexes); + Hunk_FreeTempMemory (indexOffsets); + Hunk_FreeTempMemory (baseVertexes); lod = (mdxmLOD_t *)((byte *)lod + lod->ofsEnd); } diff --git a/codemp/rd-rend2/tr_glsl.cpp b/shared/rd-rend2/tr_glsl.cpp similarity index 97% rename from codemp/rd-rend2/tr_glsl.cpp rename to shared/rd-rend2/tr_glsl.cpp index 25b289fcca..4f17034b50 100644 --- a/codemp/rd-rend2/tr_glsl.cpp +++ b/shared/rd-rend2/tr_glsl.cpp @@ -159,7 +159,7 @@ static void GLSL_PrintProgramInfoLog(GLuint object, qboolean developerOnly) } else { - char *msg = (char *)Z_Malloc(maxLength, TAG_SHADERTEXT); + char *msg = (char *)R_Malloc(maxLength, TAG_SHADERTEXT); qglGetProgramInfoLog(object, maxLength, &maxLength, msg); @@ -202,7 +202,7 @@ static void GLSL_PrintShaderInfoLog(GLuint object, qboolean developerOnly) } else { - msg = (char *)Z_Malloc(maxLength, TAG_SHADERTEXT); + msg = (char *)R_Malloc(maxLength, TAG_SHADERTEXT); qglGetShaderInfoLog(object, maxLength, &maxLength, msg); @@ -228,7 +228,7 @@ static void GLSL_PrintShaderSource(GLuint shader) return; } - char *msg = (char *)Z_Malloc(maxLength, TAG_SHADERTEXT); + char *msg = (char *)R_Malloc(maxLength, TAG_SHADERTEXT); qglGetShaderSource(shader, maxLength, nullptr, msg); for (int i = 0; i < maxLength; i += 1023) @@ -301,6 +301,8 @@ static size_t GLSL_GetShaderHeader( "#define TCGEN_LIGHTMAP3 %i\n" "#define TCGEN_TEXTURE %i\n" "#define TCGEN_ENVIRONMENT_MAPPED %i\n" + "#define TCGEN_ENVIRONMENT_MAPPED_SP %i\n" + "#define TCGEN_ENVIRONMENT_MAPPED_SP_FP %i\n" "#define TCGEN_FOG %i\n" "#define TCGEN_VECTOR %i\n" "#endif\n", @@ -310,6 +312,8 @@ static size_t GLSL_GetShaderHeader( TCGEN_LIGHTMAP3, TCGEN_TEXTURE, TCGEN_ENVIRONMENT_MAPPED, + TCGEN_ENVIRONMENT_MAPPED_SP, + TCGEN_ENVIRONMENT_MAPPED_SP_FP, TCGEN_FOG, TCGEN_VECTOR)); @@ -343,10 +347,20 @@ static size_t GLSL_GetShaderHeader( ALPHA_TEST_GE128, ALPHA_TEST_GE192)); + Q_strcat(dest, size, "#define USE_ALPHA_TEST\n"); + Q_strcat(dest, size, va("#define MAX_G2_BONES %i\n", MAX_G2_BONES)); + Q_strcat(dest, size, + va("#define MAX_GPU_FOGS %i\n", + MAX_GPU_FOGS)); + + Q_strcat(dest, size, + va("#define MAX_DLIGHTS %i\n", + MAX_DLIGHTS)); + fbufWidthScale = (float)glConfig.vidWidth; fbufHeightScale = (float)glConfig.vidHeight; Q_strcat(dest, size, @@ -756,7 +770,7 @@ bool ShaderProgramBuilder::AddShader( const GPUShaderDesc& shaderDesc, const cha bool ShaderProgramBuilder::Build( shaderProgram_t *shaderProgram ) { const size_t nameBufferSize = strlen(name) + 1; - shaderProgram->name = (char *)Z_Malloc(nameBufferSize, TAG_GENERAL); + shaderProgram->name = (char *)R_Malloc(nameBufferSize, TAG_GENERAL); Q_strncpyz(shaderProgram->name, name, nameBufferSize); shaderProgram->program = program; @@ -806,9 +820,9 @@ static bool GLSL_LoadGPUShader( void GLSL_InitUniforms(shaderProgram_t *program) { - program->uniforms = (GLint *)Z_Malloc( + program->uniforms = (GLint *)R_Malloc( UNIFORM_COUNT * sizeof(*program->uniforms), TAG_GENERAL); - program->uniformBufferOffsets = (short *)Z_Malloc( + program->uniformBufferOffsets = (short *)R_Malloc( UNIFORM_COUNT * sizeof(*program->uniformBufferOffsets), TAG_GENERAL); GLint *uniforms = program->uniforms; @@ -848,7 +862,7 @@ void GLSL_InitUniforms(shaderProgram_t *program) } } - program->uniformBuffer = (char *)Z_Malloc(size, TAG_SHADERTEXT, qtrue); + program->uniformBuffer = (char *)R_Malloc(size, TAG_SHADERTEXT, qtrue); program->uniformBlocks = 0; for ( int i = 0; i < UNIFORM_BLOCK_COUNT; ++i ) @@ -1292,10 +1306,10 @@ void GLSL_DeleteGPUShader(shaderProgram_t *program) { qglDeleteProgram(program->program); - Z_Free (program->name); - Z_Free (program->uniformBuffer); - Z_Free (program->uniformBufferOffsets); - Z_Free (program->uniforms); + Z_Free(program->name); + Z_Free(program->uniformBuffer); + Z_Free(program->uniformBufferOffsets); + Z_Free(program->uniforms); Com_Memset(program, 0, sizeof(*program)); } @@ -1303,7 +1317,7 @@ void GLSL_DeleteGPUShader(shaderProgram_t *program) static bool GLSL_IsValidPermutationForGeneric (int shaderCaps) { -#ifdef REND2_SP +#ifdef REND2_SP_MD3 if ( (shaderCaps & GENERICDEF_USE_VERTEX_ANIMATION) && (shaderCaps & GENERICDEF_USE_SKELETAL_ANIMATION) ) return false; @@ -1313,7 +1327,7 @@ static bool GLSL_IsValidPermutationForGeneric (int shaderCaps) static bool GLSL_IsValidPermutationForFog (int shaderCaps) { -#ifdef REND2_SP +#ifdef REND2_SP_MD3 if ( (shaderCaps & FOGDEF_USE_VERTEX_ANIMATION) && (shaderCaps & FOGDEF_USE_SKELETAL_ANIMATION) ) return false; @@ -1329,7 +1343,7 @@ static bool GLSL_IsValidPermutationForLight (int lightType, int shaderCaps) if (!lightType && (shaderCaps & LIGHTDEF_USE_PARALLAXMAP)) return false; -#ifdef REND2_SP +#ifdef REND2_SP_MD3 if ( (shaderCaps & LIGHTDEF_USE_SKELETAL_ANIMATION) && (shaderCaps & LIGHTDEF_USE_VERTEX_ANIMATION) ) return false; @@ -1386,7 +1400,8 @@ void GLSL_InitSplashScreenShader() size_t splashLen = strlen("splash"); tr.splashScreenShader.program = program; - tr.splashScreenShader.name = (char *)Z_Malloc(splashLen + 1, TAG_GENERAL); + tr.splashScreenShader.name = (char *)R_Malloc(splashLen + 1, TAG_GENERAL); + GLSL_InitUniforms(&tr.splashScreenShader); Q_strncpyz(tr.splashScreenShader.name, "splash", splashLen + 1); } @@ -1442,7 +1457,7 @@ static int GLSL_LoadGPUProgramGeneric( Q_strcat(extradefines, sizeof(extradefines), "#define USE_TCGEN\n"); Q_strcat(extradefines, sizeof(extradefines), "#define USE_TCMOD\n"); } -#ifdef REND2_SP +#ifdef REND2_SP_MD3 if (i & GENERICDEF_USE_VERTEX_ANIMATION) { Q_strcat(extradefines, sizeof(extradefines), "#define USE_VERTEX_ANIMATION\n"); @@ -1461,11 +1476,11 @@ static int GLSL_LoadGPUProgramGeneric( if (i & GENERICDEF_USE_RGBAGEN) Q_strcat(extradefines, sizeof(extradefines), "#define USE_RGBAGEN\n"); - if (i & GENERICDEF_USE_GLOW_BUFFER) - Q_strcat(extradefines, sizeof(extradefines), "#define USE_GLOW_BUFFER\n"); + /*if (i & GENERICDEF_USE_GLOW_BUFFER) + Q_strcat(extradefines, sizeof(extradefines), "#define USE_GLOW_BUFFER\n");*/ - if (i & GENERICDEF_USE_ALPHA_TEST) - Q_strcat(extradefines, sizeof(extradefines), "#define USE_ALPHA_TEST\n"); + /*if (i & GENERICDEF_USE_ALPHA_TEST) + Q_strcat(extradefines, sizeof(extradefines), "#define USE_ALPHA_TEST\n");*/ if (!GLSL_LoadGPUShader(builder, &tr.genericShader[i], "generic", attribs, NO_XFB_VARS, extradefines, *programDesc)) @@ -1511,11 +1526,11 @@ static int GLSL_LoadGPUProgramFogPass( if (i & FOGDEF_USE_DEFORM_VERTEXES) Q_strcat(extradefines, sizeof(extradefines), "#define USE_DEFORM_VERTEXES\n"); -#ifdef REND2_SP +#ifdef REND2_SP_MD3 if (i & FOGDEF_USE_VERTEX_ANIMATION) { Q_strcat(extradefines, sizeof(extradefines), "#define USE_VERTEX_ANIMATION\n"); - attribs |= ATTR_POSITION2 | ATTR_NORMAL2 + attribs |= ATTR_POSITION2 | ATTR_NORMAL2; } #endif // REND2_SP if (i & FOGDEF_USE_SKELETAL_ANIMATION) @@ -1527,8 +1542,8 @@ static int GLSL_LoadGPUProgramFogPass( if (i & FOGDEF_USE_FALLBACK_GLOBAL_FOG) Q_strcat(extradefines, sizeof(extradefines), "#define USE_FALLBACK_GLOBAL_FOG\n"); - if (i & FOGDEF_USE_ALPHA_TEST) - Q_strcat(extradefines, sizeof(extradefines), "#define USE_ALPHA_TEST\n"); + /*if (i & FOGDEF_USE_ALPHA_TEST) + Q_strcat(extradefines, sizeof(extradefines), "#define USE_ALPHA_TEST\n");*/ if (!GLSL_LoadGPUShader(builder, &tr.fogShader[i], "fogpass", attribs, NO_XFB_VARS, extradefines, *programDesc)) @@ -1539,7 +1554,7 @@ static int GLSL_LoadGPUProgramFogPass( GLSL_InitUniforms(&tr.fogShader[i]); qglUseProgram(tr.fogShader[i].program); - if (i & FOGDEF_USE_ALPHA_TEST) + //if (i & FOGDEF_USE_ALPHA_TEST) GLSL_SetUniformInt(&tr.fogShader[i], UNIFORM_DIFFUSEMAP, 0); qglUseProgram(0); @@ -1574,7 +1589,7 @@ static int GLSL_LoadGPUProgramRefraction( Q_strcat(extradefines, sizeof(extradefines), "#define USE_TCGEN\n"); Q_strcat(extradefines, sizeof(extradefines), "#define USE_TCMOD\n"); } -#ifdef REND2_SP +#ifdef REND2_SP_MD3 if (i & REFRACTIONDEF_USE_VERTEX_ANIMATION) { Q_strcat(extradefines, sizeof(extradefines), "#define USE_VERTEX_ANIMATION\n"); @@ -1590,8 +1605,8 @@ static int GLSL_LoadGPUProgramRefraction( if (i & REFRACTIONDEF_USE_RGBAGEN) Q_strcat(extradefines, sizeof(extradefines), "#define USE_RGBAGEN\n"); - if (i & REFRACTIONDEF_USE_ALPHA_TEST) - Q_strcat(extradefines, sizeof(extradefines), "#define USE_ALPHA_TEST\n"); + /*if (i & REFRACTIONDEF_USE_ALPHA_TEST) + Q_strcat(extradefines, sizeof(extradefines), "#define USE_ALPHA_TEST\n");*/ if (i & REFRACTIONDEF_USE_SRGB_TRANSFORM) Q_strcat(extradefines, sizeof(extradefines), "#define USE_LINEAR_LIGHT\n"); @@ -1739,7 +1754,7 @@ static int GLSL_LoadGPUProgramLightAll( { Q_strcat(extradefines, sizeof(extradefines), "#define USE_CLOTH_BRDF\n"); } -#ifdef REND2_SP +#ifdef REND2_SP_MD3 if (i & LIGHTDEF_USE_VERTEX_ANIMATION) { Q_strcat(extradefines, sizeof(extradefines), "#define USE_VERTEX_ANIMATION\n"); @@ -1756,11 +1771,11 @@ static int GLSL_LoadGPUProgramLightAll( attribs |= ATTR_BONE_INDEXES | ATTR_BONE_WEIGHTS; } - if (i & LIGHTDEF_USE_ALPHA_TEST) - Q_strcat(extradefines, sizeof(extradefines), "#define USE_ALPHA_TEST\n"); + /*if (i & LIGHTDEF_USE_ALPHA_TEST) + Q_strcat(extradefines, sizeof(extradefines), "#define USE_ALPHA_TEST\n");*/ - if (i & LIGHTDEF_USE_GLOW_BUFFER) - Q_strcat(extradefines, sizeof(extradefines), "#define USE_GLOW_BUFFER\n"); + /*if (i & LIGHTDEF_USE_GLOW_BUFFER) + Q_strcat(extradefines, sizeof(extradefines), "#define USE_GLOW_BUFFER\n");*/ if (!GLSL_LoadGPUShader(builder, &tr.lightallShader[i], "lightall", attribs, NO_XFB_VARS, extradefines, *programDesc)) @@ -2225,9 +2240,9 @@ static int GLSL_LoadGPUProgramSurfaceSprites( Q_strcat(extradefines, sizeof(extradefines), "#define USE_FOG\n"); - if ( i & SSDEF_ALPHA_TEST ) + /*if ( i & SSDEF_ALPHA_TEST ) Q_strcat(extradefines, sizeof(extradefines), - "#define ALPHA_TEST\n"); + "#define USE_ALPHA_TEST\n");*/ if (i & SSDEF_ADDITIVE) Q_strcat(extradefines, sizeof(extradefines), @@ -2528,7 +2543,7 @@ void GL_VertexArraysToAttribs( { 4, GL_FALSE, GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE }, // light direction { 4, GL_TRUE, GL_UNSIGNED_BYTE, GL_FALSE }, // bone indices { 4, GL_FALSE, GL_UNSIGNED_BYTE, GL_TRUE }, // bone weights -#ifdef REND2_SP +#ifdef REND2_SP_MD3 { 3, GL_FALSE, GL_FLOAT, GL_FALSE }, // pos2 { 4, GL_FALSE, GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE }, // tangent2 { 4, GL_FALSE, GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE }, // normal2 @@ -2571,8 +2586,8 @@ shaderProgram_t *GLSL_GetGenericShaderProgram(int stage) shaderStage_t *pStage = tess.xstages[stage]; int shaderAttribs = 0; - if ( pStage->alphaTestType != ALPHA_TEST_NONE ) - shaderAttribs |= GENERICDEF_USE_ALPHA_TEST; + /*if ( pStage->alphaTestType != ALPHA_TEST_NONE ) + shaderAttribs |= GENERICDEF_USE_ALPHA_TEST;*/ if (backEnd.currentEntity->e.renderfx & (RF_DISINTEGRATE1 | RF_DISINTEGRATE2)) shaderAttribs |= GENERICDEF_USE_RGBAGEN; @@ -2613,7 +2628,7 @@ shaderProgram_t *GLSL_GetGenericShaderProgram(int stage) { shaderAttribs |= GENERICDEF_USE_DEFORM_VERTEXES; } -#ifdef REND2_SP +#ifdef REND2_SP_MD3 if (glState.vertexAnimation) { shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION; @@ -2629,10 +2644,10 @@ shaderProgram_t *GLSL_GetGenericShaderProgram(int stage) shaderAttribs |= GENERICDEF_USE_TCGEN_AND_TCMOD; } - if (pStage->glow) + /*if (pStage->glow) { shaderAttribs |= GENERICDEF_USE_GLOW_BUFFER; - } + }*/ return &tr.genericShader[shaderAttribs]; } diff --git a/codemp/rd-rend2/tr_glsl_parse.cpp b/shared/rd-rend2/tr_glsl_parse.cpp similarity index 100% rename from codemp/rd-rend2/tr_glsl_parse.cpp rename to shared/rd-rend2/tr_glsl_parse.cpp diff --git a/codemp/rd-rend2/tr_image.cpp b/shared/rd-rend2/tr_image.cpp similarity index 97% rename from codemp/rd-rend2/tr_image.cpp rename to shared/rd-rend2/tr_image.cpp index 62d4c29e6e..b7d1f026cf 100644 --- a/codemp/rd-rend2/tr_image.cpp +++ b/shared/rd-rend2/tr_image.cpp @@ -37,6 +37,7 @@ static struct ImagesPool image_t *pPool; ImagesPool *pNext; } *imagesPool; +static bool imagePoolInitialized = false; static image_t *hashTable[FILE_HASH_SIZE]; @@ -45,8 +46,8 @@ Extends the size of the images pool allocator */ static void R_ExtendImagesPool() { - ImagesPool *pool = (ImagesPool *)Z_Malloc(sizeof(*pool), TAG_GENERAL); - image_t *freeImages = (image_t *)Z_Malloc(sizeof(*freeImages) * NUM_IMAGES_PER_POOL_ALLOC, TAG_IMAGE_T); + ImagesPool *pool = (ImagesPool *)R_Malloc(sizeof(*pool), TAG_GENERAL); + image_t *freeImages = (image_t *)R_Malloc(sizeof(*freeImages) * NUM_IMAGES_PER_POOL_ALLOC, TAG_IMAGE_T); for ( int i = 0; i < (NUM_IMAGES_PER_POOL_ALLOC - 1); i++ ) { @@ -1319,7 +1320,7 @@ static void R_MipMap2( byte *in, int inWidth, int inHeight ) { outWidth = inWidth >> 1; outHeight = inHeight >> 1; - temp = (unsigned int *)ri.Hunk_AllocateTempMemory( outWidth * outHeight * 4 ); + temp = (unsigned int *)Hunk_AllocateTempMemory( outWidth * outHeight * 4 ); inWidthMask = inWidth - 1; inHeightMask = inHeight - 1; @@ -1354,7 +1355,7 @@ static void R_MipMap2( byte *in, int inWidth, int inHeight ) { } Com_Memcpy( in, temp, outWidth * outHeight * 4 ); - ri.Hunk_FreeTempMemory( temp ); + Hunk_FreeTempMemory( temp ); } @@ -1369,7 +1370,7 @@ static void R_MipMapsRGB( byte *in, int inWidth, int inHeight) outWidth = inWidth >> 1; outHeight = inHeight >> 1; - temp = (byte *)ri.Hunk_AllocateTempMemory( outWidth * outHeight * 4 ); + temp = (byte *)Hunk_AllocateTempMemory( outWidth * outHeight * 4 ); for ( i = 0 ; i < outHeight ; i++ ) { byte *outbyte = temp + ( i * outWidth ) * 4; @@ -1399,7 +1400,7 @@ static void R_MipMapsRGB( byte *in, int inWidth, int inHeight) } Com_Memcpy( in, temp, outWidth * outHeight * 4 ); - ri.Hunk_FreeTempMemory( temp ); + Hunk_FreeTempMemory( temp ); } /* @@ -1625,7 +1626,7 @@ static void RawImage_ScaleToPower2( byte **data, int *inout_width, int *inout_he finalheight >>= 1; } - *resampledBuffer = (byte *)ri.Hunk_AllocateTempMemory( finalwidth * finalheight * 4 ); + *resampledBuffer = (byte *)Hunk_AllocateTempMemory( finalwidth * finalheight * 4 ); if (scaled_width != width || scaled_height != height) { @@ -1677,7 +1678,7 @@ static void RawImage_ScaleToPower2( byte **data, int *inout_width, int *inout_he else if ( scaled_width != width || scaled_height != height ) { if (data && resampledBuffer) { - *resampledBuffer = (byte *)ri.Hunk_AllocateTempMemory( scaled_width * scaled_height * 4 ); + *resampledBuffer = (byte *)Hunk_AllocateTempMemory( scaled_width * scaled_height * 4 ); ResampleTexture (*data, width, height, *resampledBuffer, scaled_width, scaled_height); *data = *resampledBuffer; } @@ -2102,7 +2103,7 @@ static void Upload32( byte *data, int width, int height, imgType_t type, int fla RawImage_ScaleToPower2(&data, &width, &height, &scaled_width, &scaled_height, type, flags, &resampledBuffer); } - scaledBuffer = (byte *)ri.Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height ); + scaledBuffer = (byte *)Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height ); // // scan the texture for each channel's max values @@ -2221,9 +2222,9 @@ static void Upload32( byte *data, int width, int height, imgType_t type, int fla GL_CheckErrors(); if ( scaledBuffer != 0 ) - ri.Hunk_FreeTempMemory( scaledBuffer ); + Hunk_FreeTempMemory( scaledBuffer ); if ( resampledBuffer != 0 ) - ri.Hunk_FreeTempMemory( resampledBuffer ); + Hunk_FreeTempMemory( resampledBuffer ); } @@ -2606,7 +2607,7 @@ void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int h RawImage_ScaleToPower2(&pic, &width, &height, &scaled_width, &scaled_height, image->type, image->flags, &resampledBuffer); - scaledBuffer = (byte *)ri.Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height ); + scaledBuffer = (byte *)Hunk_AllocateTempMemory( sizeof( unsigned ) * scaled_width * scaled_height ); GL_SelectTexture( image->TMU ); GL_Bind(image); @@ -2672,9 +2673,9 @@ void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int h GL_CheckErrors(); if ( scaledBuffer != 0 ) - ri.Hunk_FreeTempMemory( scaledBuffer ); + Hunk_FreeTempMemory( scaledBuffer ); if ( resampledBuffer != 0 ) - ri.Hunk_FreeTempMemory( resampledBuffer ); + Hunk_FreeTempMemory( resampledBuffer ); } image_t* R_GetLoadedImage(const char *name, int flags) { @@ -2814,7 +2815,7 @@ image_t *R_BuildSDRSpecGlossImage(shaderStage_t *stage, const char *specImageNam if (specPic == NULL) return NULL; - byte *sdrSpecPic = (byte *)ri.Hunk_AllocateTempMemory(sizeof(unsigned) * specWidth * specHeight); + byte *sdrSpecPic = (byte *)Hunk_AllocateTempMemory(sizeof(unsigned) * specWidth * specHeight); vec3_t currentColor; for (int i = 0; i < specWidth * specHeight * 4; i += 4) { @@ -2831,9 +2832,12 @@ image_t *R_BuildSDRSpecGlossImage(shaderStage_t *stage, const char *specImageNam sdrSpecPic[i + 2] = FloatToByte(currentColor[2] * ratio); sdrSpecPic[i + 3] = specPic[i + 3]; } - ri.Hunk_FreeTempMemory(specPic); + Hunk_FreeTempMemory(specPic); - return R_CreateImage(sdrName, sdrSpecPic, specWidth, specHeight, IMGTYPE_COLORALPHA, flags & ~IMGFLAG_SRGB, 0); + image_t *outImage = R_CreateImage(sdrName, sdrSpecPic, specWidth, specHeight, IMGTYPE_COLORALPHA, flags & ~IMGFLAG_SRGB, 0); + Hunk_FreeTempMemory(sdrSpecPic); + + return outImage; } static void R_CreateNormalMap ( const char *name, byte *pic, int width, int height, int flags ) @@ -2859,7 +2863,7 @@ static void R_CreateNormalMap ( const char *name, byte *pic, int width, int heig normalWidth = width; normalHeight = height; - normalPic = (byte *)Z_Malloc(width * height * 4, TAG_GENERAL); + normalPic = (byte *)R_Malloc(width * height * 4, TAG_TEMP_WORKSPACE); RGBAtoNormal(pic, normalPic, width, height, (qboolean)(flags & IMGFLAG_CLAMPTOEDGE)); #if 1 @@ -2965,11 +2969,11 @@ image_t *R_FindImageFile( const char *name, imgType_t type, int flags ) // // load the pic from disk // - if (r_hdr->integer && (flags & IMGFLAG_HDR || flags & IMGFLAG_HDR_LIGHTMAP)) + if (r_hdr->integer && flags & IMGFLAG_HDR) { char filename[MAX_QPATH]; Com_sprintf(filename, sizeof(filename), "%s.hdr", name); - float *floatBuffer; + R_LoadHDRImage(filename, &pic, &width, &height); if (pic == NULL) { @@ -2977,23 +2981,13 @@ image_t *R_FindImageFile( const char *name, imgType_t type, int flags ) } else { + float *floatBuffer = (float*)pic; for (int i = 0; i < width*height; i++) { - vec4_t color; - floatBuffer = (float*)pic; - memcpy(color, &floatBuffer[i*3], 12); - if (flags & IMGFLAG_HDR_LIGHTMAP) - { - color[0] = color[0] / M_PI; - color[1] = color[1] / M_PI; - color[2] = color[2] / M_PI; - } - color[3] = 1.0f; - uint16_t *hdr_color = (uint16_t *)(&pic[i * 8]); - hdr_color[0] = FloatToHalf(color[0]); - hdr_color[1] = FloatToHalf(color[1]); - hdr_color[2] = FloatToHalf(color[2]); + hdr_color[0] = FloatToHalf(floatBuffer[i * 3]); + hdr_color[1] = FloatToHalf(floatBuffer[i * 3 + 1]); + hdr_color[2] = FloatToHalf(floatBuffer[i * 3 + 2]); hdr_color[3] = FloatToHalf(1.0f); } internalFormat = GL_RGBA16F; @@ -3144,7 +3138,7 @@ static void R_CreateFogImage( void ) { float d; float borderColor[4]; - data = (byte *)ri.Hunk_AllocateTempMemory( FOG_S * FOG_T * 4 ); + data = (byte *)Hunk_AllocateTempMemory( FOG_S * FOG_T * 4 ); // S is distance, T is depth for (x=0 ; x. static void* R_LocalMalloc(size_t size) { - return ri.Hunk_AllocateTempMemory(size); + return Hunk_AllocateTempMemory(size); } static void* R_LocalReallocSized(void *ptr, size_t old_size, size_t new_size) { - void *mem = ri.Hunk_AllocateTempMemory(new_size); + void *mem = Hunk_AllocateTempMemory(new_size); if (ptr) { memcpy(mem, ptr, old_size); - ri.Hunk_FreeTempMemory(ptr); + Hunk_FreeTempMemory(ptr); } return mem; } static void R_LocalFree(void *ptr) { if (ptr) - ri.Hunk_FreeTempMemory(ptr); + Hunk_FreeTempMemory(ptr); } #define STBI_MALLOC R_LocalMalloc @@ -66,6 +66,11 @@ void R_LoadHDRImage( const char *filename, byte **data, int *width, int *height int len = ri.FS_ReadFile (filename, (void **)&buf); if ( len <= 0 || buf == NULL ) { + // reset output varialbes + *data = NULL; + *width = 0; + *height = 0; + return; } stbi_set_flip_vertically_on_load(0); diff --git a/codemp/rd-rend2/tr_light.cpp b/shared/rd-rend2/tr_light.cpp similarity index 90% rename from codemp/rd-rend2/tr_light.cpp rename to shared/rd-rend2/tr_light.cpp index 27a368c77b..242fe9d190 100644 --- a/codemp/rd-rend2/tr_light.cpp +++ b/shared/rd-rend2/tr_light.cpp @@ -90,9 +90,10 @@ void R_DlightBmodel( bmodel_t *bmodel, trRefEntity_t *ent ) { ent->needDlights = (qboolean)(mask != 0); + world_t *world = R_GetWorld(bmodel->worldIndex); // set the dlight bits in all the surfaces for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) { - surf = tr.world->surfaces + bmodel->firstSurface + i; + surf = world->surfaces + bmodel->firstSurface + i; switch(*surf->data) { @@ -137,7 +138,15 @@ static void R_SetupEntityLightingGrid( trRefEntity_t *ent, world_t *world ) { vec3_t direction; float totalFactor; uint32_t startGridPos; - +#ifdef REND2_SP + if (r_fullbright->integer || tr.refdef.doLAGoggles) + { + ent->ambientLight[0] = ent->ambientLight[1] = ent->ambientLight[2] = 255.0f; + ent->directedLight[0] = ent->directedLight[1] = ent->directedLight[2] = 255.0f; + VectorCopy(tr.sunDirection, ent->lightDir); + return; + } +#endif if ( ent->e.renderfx & RF_LIGHTING_ORIGIN ) { // seperate lightOrigins are needed so an object that is // sinking into the ground can still be lit, and so @@ -360,14 +369,6 @@ void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ) { // only do min lighting when there is no hdr light data if (tr.hdrLighting != qtrue) { - // bonus items and view weapons have a fixed minimum add - if (1/*!r_hdr->integer*/) { - // give everything a minimum light add - ent->ambientLight[0] += tr.identityLight * 32; - ent->ambientLight[1] += tr.identityLight * 32; - ent->ambientLight[2] += tr.identityLight * 32; - } - if (ent->e.renderfx & RF_MINLIGHT) { //the minlight flag is now for items rotating on their holo thing if (ent->e.shaderRGBA[0] == 255 && @@ -385,6 +386,18 @@ void R_SetupEntityLighting( const trRefdef_t *refdef, trRefEntity_t *ent ) { ent->ambientLight[2] += tr.identityLight * 150; } } + // bonus items and view weapons have a fixed minimum add + else if (ent->e.renderfx & RF_MORELIGHT) { + ent->ambientLight[0] += tr.identityLight * 96; + ent->ambientLight[1] += tr.identityLight * 96; + ent->ambientLight[2] += tr.identityLight * 96; + } + else { + // give everything a minimum light add + ent->ambientLight[0] += tr.identityLight * 32; + ent->ambientLight[1] += tr.identityLight * 32; + ent->ambientLight[2] += tr.identityLight * 32; + } } d = VectorLength( ent->directedLight ); @@ -447,7 +460,10 @@ int R_LightDirForPoint( vec3_t point, vec3_t lightDir, vec3_t normal, world_t *w trRefEntity_t ent; if ( world->lightGridData == NULL ) - return qfalse; + { + VectorCopy(normal, lightDir); + return qfalse; + } Com_Memset(&ent, 0, sizeof(ent)); VectorCopy( point, ent.e.origin ); @@ -509,3 +525,30 @@ int R_CubemapForPoint( const vec3_t point ) return cubemapIndex + 1; } + +#ifdef REND2_SP +//pass in origin +qboolean RE_GetLighting(const vec3_t origin, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir) { + trRefEntity_t tr_ent; + + if (!tr.world || !tr.world->lightGridData) { + ambientLight[0] = ambientLight[1] = ambientLight[2] = 255.0; + directedLight[0] = directedLight[1] = directedLight[2] = 255.0; + VectorCopy(tr.sunDirection, lightDir); + return qfalse; + } + memset(&tr_ent, 0, sizeof(tr_ent)); + + if (ambientLight[0] == 666) + {//HAX0R + tr_ent.e.hModel = -1; + } + + VectorCopy(origin, tr_ent.e.origin); + R_SetupEntityLightingGrid(&tr_ent, tr.world); + VectorCopy(tr_ent.ambientLight, ambientLight); + VectorCopy(tr_ent.directedLight, directedLight); + VectorCopy(tr_ent.lightDir, lightDir); + return qtrue; +} +#endif \ No newline at end of file diff --git a/codemp/rd-rend2/tr_local.h b/shared/rd-rend2/tr_local.h similarity index 96% rename from codemp/rd-rend2/tr_local.h rename to shared/rd-rend2/tr_local.h index f03215cd0f..75139dc36c 100644 --- a/codemp/rd-rend2/tr_local.h +++ b/shared/rd-rend2/tr_local.h @@ -41,6 +41,20 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include +#ifdef REND2_SP +typedef enum { + h_high, + h_low, + h_dontcare +} ha_pref; +void* Hunk_Alloc(int size, ha_pref preference); +void* Hunk_AllocateTempMemory(int size); +void Hunk_FreeTempMemory(void* buf); +#else +void* R_Malloc(int iSize, memtag_t eTag); +void* R_Malloc(int iSize, memtag_t eTag, qboolean bZeroit); +#endif + #define GL_INDEX_TYPE GL_UNSIGNED_INT typedef unsigned int glIndex_t; @@ -57,6 +71,7 @@ typedef unsigned int glIndex_t; #define MAX_VBOS 4096 #define MAX_IBOS 4096 #define MAX_G2_BONES 72 +#define MAX_GPU_FOGS 24 #define MAX_CALC_PSHADOWS 64 #define MAX_DRAWN_PSHADOWS 32 // do not increase past 32, because bit flags are used on surfaces @@ -313,10 +328,9 @@ typedef enum IMGFLAG_GENNORMALMAP = 0x0100, IMGFLAG_MUTABLE = 0x0200, IMGFLAG_HDR = 0x0400, - IMGFLAG_HDR_LIGHTMAP = 0x0800, - IMGFLAG_2D_ARRAY = 0x1000, - IMGFLAG_3D = 0x2000, - IMGLFAG_SHADOWCOMP = 0x4000, + IMGFLAG_2D_ARRAY = 0x0800, + IMGFLAG_3D = 0x1000, + IMGLFAG_SHADOWCOMP = 0x2000, } imgFlags_t; typedef enum @@ -343,7 +357,7 @@ enum // GPU vertex animations and some extra sprite info ATTR_INDEX_POSITION2, -#ifdef REND2_SP +#ifdef REND2_SP_MD3 ATTR_INDEX_TANGENT2, ATTR_INDEX_NORMAL2, #endif // REND2_SP @@ -592,6 +606,8 @@ typedef enum { TCGEN_LIGHTMAP3, TCGEN_TEXTURE, TCGEN_ENVIRONMENT_MAPPED, + TCGEN_ENVIRONMENT_MAPPED_SP, + TCGEN_ENVIRONMENT_MAPPED_SP_FP, TCGEN_FOG, TCGEN_VECTOR // S and T from world coordinates } texCoordGen_t; @@ -753,7 +769,7 @@ struct FogsBlock int numFogs; float pad0[3]; - Fog fogs[16]; + Fog fogs[MAX_GPU_FOGS]; }; struct EntityBlock @@ -761,13 +777,11 @@ struct EntityBlock matrix_t modelMatrix; vec4_t lightOrigin; vec3_t ambientLight; - float lightRadius; + float entityTime; vec3_t directedLight; float fxVolumetricBase; vec3_t modelLightDir; float vertexLerp; - vec3_t localViewOrigin; - float entityTime; }; struct ShaderInstanceBlock @@ -1106,6 +1120,8 @@ enum GLS_POLYGON_OFFSET_FILL = (1 << 28), + GLS_COLORMASK_BUF1 = (1 << 29), + GLS_DEFAULT = GLS_DEPTHMASK_TRUE }; @@ -1141,7 +1157,7 @@ enum // for .md3 interpolation and some sprite data ATTR_POSITION2 = 0x1000, -#ifdef REND2_SP +#ifdef REND2_SP_MD3 ATTR_TANGENT2 = 0x2000, ATTR_NORMAL2 = 0x4000, #endif // REND2_SP @@ -1160,8 +1176,8 @@ enum ATTR_BONE_INDEXES | ATTR_BONE_WEIGHTS | ATTR_POSITION2 -#ifdef REND2_SP - | +#ifdef REND2_SP_MD3 + | ATTR_TANGENT2 | ATTR_NORMAL2 #endif // REND2_SP @@ -1174,13 +1190,13 @@ enum GENERICDEF_USE_FOG = 0x0004, GENERICDEF_USE_RGBAGEN = 0x0008, GENERICDEF_USE_SKELETAL_ANIMATION = 0x0010, - GENERICDEF_USE_GLOW_BUFFER = 0x0020, - GENERICDEF_USE_ALPHA_TEST = 0x0040, -#ifdef REND2_SP + // GENERICDEF_USE_GLOW_BUFFER = 0x0020, + // GENERICDEF_USE_ALPHA_TEST = 0x0040, +#ifdef REND2_SP_MD3 GENERICDEF_USE_VERTEX_ANIMATION = 0x0080, GENERICDEF_ALL = 0x00FF, #else - GENERICDEF_ALL = 0x007F, + GENERICDEF_ALL = 0x001F, #endif // REND2_SP GENERICDEF_COUNT = GENERICDEF_ALL + 1, @@ -1190,13 +1206,13 @@ enum { FOGDEF_USE_DEFORM_VERTEXES = 0x0001, FOGDEF_USE_SKELETAL_ANIMATION = 0x0002, - FOGDEF_USE_ALPHA_TEST = 0x0004, - FOGDEF_USE_FALLBACK_GLOBAL_FOG = 0x0008, -#ifdef REND2_SP + //FOGDEF_USE_ALPHA_TEST = 0x0004, + FOGDEF_USE_FALLBACK_GLOBAL_FOG = 0x0004, +#ifdef REND2_SP_MD3 FOGDEF_USE_VERTEX_ANIMATION = 0x0010, FOGDEF_ALL = 0x001F, #else - FOGDEF_ALL = 0x000F, + FOGDEF_ALL = 0x0007, #endif // REND2_SP FOGDEF_COUNT = FOGDEF_ALL + 1, @@ -1208,13 +1224,13 @@ enum REFRACTIONDEF_USE_TCGEN_AND_TCMOD = 0x0002, REFRACTIONDEF_USE_RGBAGEN = 0x0004, REFRACTIONDEF_USE_SKELETAL_ANIMATION = 0x0008, - REFRACTIONDEF_USE_ALPHA_TEST = 0x0010, - REFRACTIONDEF_USE_SRGB_TRANSFORM = 0x0020, -#ifdef REND2_SP + //REFRACTIONDEF_USE_ALPHA_TEST = 0x0010, + REFRACTIONDEF_USE_SRGB_TRANSFORM = 0x0010, +#ifdef REND2_SP_MD3 REFRACTIONDEF_USE_VERTEX_ANIMATION = 0x0040, REFRACTIONDEF_ALL = 0x007F, #else - REFRACTIONDEF_ALL = 0x003F, + REFRACTIONDEF_ALL = 0x001F, #endif // REND2_SP REFRACTIONDEF_COUNT = REFRACTIONDEF_ALL + 1, @@ -1229,20 +1245,20 @@ enum LIGHTDEF_USE_PARALLAXMAP = 0x0008, // LIGHTDEF_USE_SHADOWMAP = 0x0010, LIGHTDEF_USE_SKELETAL_ANIMATION = 0x0010, - LIGHTDEF_USE_GLOW_BUFFER = 0x0020, - LIGHTDEF_USE_ALPHA_TEST = 0x0040, - LIGHTDEF_USE_CLOTH_BRDF = 0x0080, - LIGHTDEF_USE_SPEC_GLOSS = 0x0100, + //LIGHTDEF_USE_GLOW_BUFFER = 0x0020, + //LIGHTDEF_USE_ALPHA_TEST = 0x0040, + LIGHTDEF_USE_CLOTH_BRDF = 0x0020, + LIGHTDEF_USE_SPEC_GLOSS = 0x0040, LIGHTDEF_LIGHTTYPE_MASK = LIGHTDEF_USE_LIGHTMAP | LIGHTDEF_USE_LIGHT_VECTOR | LIGHTDEF_USE_LIGHT_VERTEX, -#ifdef REND2_SP +#ifdef REND2_SP_MD3 LIGHTDEF_USE_VERTEX_ANIMATION = 0x0200, LIGHTDEF_ALL = 0x03FF, #else - LIGHTDEF_ALL = 0x01FF, + LIGHTDEF_ALL = 0x007F, #endif // REND2_SP LIGHTDEF_COUNT = LIGHTDEF_ALL + 1 @@ -1251,15 +1267,15 @@ enum enum { SSDEF_FACE_CAMERA = 0x01, - SSDEF_ALPHA_TEST = 0x02, - SSDEF_FACE_UP = 0x04, - SSDEF_FX_SPRITE = 0x08, - SSDEF_USE_FOG = 0x10, - SSDEF_FOG_MODULATE = 0x20, - SSDEF_ADDITIVE = 0x40, - SSDEF_FLATTENED = 0x80, - - SSDEF_ALL = 0xFF, + //SSDEF_ALPHA_TEST = 0x02, + SSDEF_FACE_UP = 0x02, + SSDEF_FX_SPRITE = 0x04, + SSDEF_USE_FOG = 0x08, + SSDEF_FOG_MODULATE = 0x10, + SSDEF_ADDITIVE = 0x20, + SSDEF_FLATTENED = 0x40, + + SSDEF_ALL = 0x7F, SSDEF_COUNT = SSDEF_ALL + 1 }; @@ -1498,11 +1514,27 @@ typedef struct { float autoExposureMinMax[2]; float toneMinAvgMaxLinear[3]; +#ifdef REND2_SP + bool doLAGoggles; + bool doFullbright; +#endif } trRefdef_t; //================================================================================= +// skins allow models to be retextured without modifying the model file +typedef struct { + char name[MAX_QPATH]; + shader_t *shader; +} skinSurface_t; + +typedef struct skin_s { + char name[MAX_QPATH]; // game path, including extension + int numSurfaces; + skinSurface_t *surfaces[128]; +} skin_t; + typedef struct { int originalBrushNumber; @@ -1553,7 +1585,6 @@ typedef struct { int frameCount; // copied from tr.frameCount cplane_t portalPlane; // clip anything behind this if mirroring int viewportX, viewportY, viewportWidth, viewportHeight; - int scissorX, scissorY, scissorWidth, scissorHeight; FBO_t *targetFbo; int targetFboLayer; float fovX, fovY; @@ -2226,8 +2257,11 @@ typedef struct glstate_s { int currenttmu; int texEnv[2]; int faceCulling; + bool blend; float minDepth; float maxDepth; + ivec2_t viewportOrigin; + ivec2_t viewportSize; uint32_t glStateBits; uint32_t vertexAttribsState; vertexAttribute_t currentVaoAttribs[ATTR_INDEX_MAX]; @@ -2625,20 +2659,22 @@ typedef struct trGlobals_s { // Specific to Jedi Academy int numBSPModels; int currentLevel; - - bool explicitToneMap; } trGlobals_t; struct glconfigExt_t { glconfig_t *glConfig; + qboolean textureFilterAnisotropicAvailable; + qboolean doGammaCorrectionWithShaders; + qboolean doStencilShadowsInOneDrawcall; const char *originalExtensionString; }; extern backEndState_t backEnd; extern trGlobals_t tr; extern glstate_t glState; // outside of TR since it shouldn't be cleared during ref re-init +extern glconfigExt_t glConfigExt; extern glRefConfig_t glRefConfig; extern window_t window; @@ -2889,6 +2925,7 @@ void GL_CheckErrs( const char *file, int line ); void GL_State( uint32_t stateVector ); void GL_SetProjectionMatrix(matrix_t matrix); void GL_SetModelviewMatrix(matrix_t matrix); +void GL_SetViewportAndScissor(int viewportX, int viewportY, int viewportWidth, int viewportHeight); void GL_Cull( int cullType ); void GL_DepthRange( float min, float max ); void GL_VertexAttribPointers(size_t numAttributes, @@ -2905,12 +2942,15 @@ void GL_Draw( GLenum primitiveType, int firstVertex, int numVertices, int numIns extern glconfig_t glConfig; extern glconfigExt_t glConfigExt; -typedef _skinSurface_t skinSurface_t; - void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty); void RE_UploadCinematic (int cols, int rows, const byte *data, int client, qboolean dirty); void RE_SetRangedFog ( float range ); - +#ifdef REND2_SP +byte *RB_ReadPixels(int x, int y, int width, int height, size_t *offset, int *padlen); +void RE_GetScreenShot(byte *data, int w, int h); +byte* RE_TempRawImage_ReadFromFile(const char *psLocalFilename, int *piWidth, int *piHeight, byte *pbReSampleBuffer, qboolean qbVertFlip); +void RE_TempRawImage_CleanUp(); +#endif void RE_BeginRegistration( glconfig_t *glconfig ); void RE_LoadWorldMap( const char *mapname ); @@ -2922,6 +2962,10 @@ qhandle_t RE_RegisterSkin( const char *name ); void RE_Shutdown(qboolean destroyWindow, qboolean restarting); world_t *R_LoadBSP(const char *name, int *bspIndex = nullptr); +#ifdef REND2_SP +int RE_GetAnimationCFG(const char* psCFGFilename, char* psDest, int iDestSize); +#endif + qboolean R_GetEntityToken( char *buffer, int size ); model_t *R_AllocModel( void ); @@ -3030,7 +3074,7 @@ struct shaderCommands_s float shaderTime; int fogNum; int cubemapIndex; -#ifdef REND2_SP_MAYBE +#ifdef REND2_SP_GORE bool scale; // uses texCoords[input->firstIndex] for storage bool fade; // uses svars.colors[input->firstIndex] for storage #endif @@ -3099,8 +3143,11 @@ void R_AddBrushModelSurfaces( trRefEntity_t *e, int entityNum ); void R_AddWorldSurfaces( viewParms_t *viewParms, trRefdef_t *refdef ); void R_MarkLeaves(void); void R_RecursiveWorldNode(mnode_t *node, int planeBits, int dlightBits, int pshadowBits); +#ifndef REND2_SP qboolean R_inPVS( const vec3_t p1, const vec3_t p2, byte *mask ); - +#else +qboolean R_inPVS(vec3_t p1, vec3_t p2); +#endif /* ============================================================ @@ -3131,6 +3178,9 @@ int R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, ve int R_LightDirForPoint( vec3_t point, vec3_t lightDir, vec3_t normal, world_t *world ); int R_DLightsForPoint(const vec3_t point, const float radius); int R_CubemapForPoint( const vec3_t point ); +#ifdef REND2_SP +qboolean RE_GetLighting(const vec3_t origin, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir); +#endif /* ============================================================ @@ -3283,7 +3333,7 @@ void R_InitNextFrame( void ); void RE_ClearScene( void ); void RE_AddRefEntityToScene( const refEntity_t *ent ); void RE_AddMiniRefEntityToScene( const miniRefEntity_t *miniRefEnt ); -void RE_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts, int num ); +void RE_AddPolyToScene(qhandle_t hShader, int numVerts, const polyVert_t *verts, int num = 1); void RE_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b ); void RE_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, float g, float b ); void RE_BeginScene( const refdef_t *fd ); @@ -3307,8 +3357,6 @@ UNCOMPRESSING BONES #define MC_SCALE_Y (1.0f/64) #define MC_SCALE_Z (1.0f/64) -void MC_UnCompress(float mat[3][4],const unsigned char * comp); - /* ============================================================= @@ -3512,6 +3560,14 @@ typedef struct rotatePicCommand_s { float a; } rotatePicCommand_t; +#ifdef REND2_SP +typedef struct scissorCommand_s { + int commandId; + float x, y; + float w, h; +} scissorCommand_t; +#endif + typedef struct drawSurfsCommand_s { int commandId; trRefdef_t refdef; @@ -3589,6 +3645,7 @@ typedef enum { RC_SWAP_BUFFERS, RC_SCREENSHOT, RC_VIDEOFRAME, + RC_SCISSOR, RC_COLORMASK, RC_CLEARDEPTH, RC_CONVOLVECUBEMAP, @@ -3622,14 +3679,16 @@ struct screenshotReadback_t }; #define MAX_GPU_TIMERS (512) +#define MAX_SCENES (3) struct gpuFrame_t { GLsync sync; - GLuint ubo; - size_t uboWriteOffset; - size_t uboSize; - size_t uboMapBase; - void *uboMemory; + byte currentScene; + GLuint ubo[MAX_SCENES]; + size_t uboWriteOffset[MAX_SCENES]; + size_t uboSize[MAX_SCENES]; + size_t uboMapBase[MAX_SCENES]; + void *uboMemory[MAX_SCENES]; screenshotReadback_t screenshotReadback; @@ -3694,6 +3753,10 @@ void RE_SetColor( const float *rgba ); void RE_StretchPic ( float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t hShader ); void RE_RotatePic ( float x, float y, float w, float h, float s1, float t1, float s2, float t2, float a, qhandle_t hShader ); void RE_RotatePic2 ( float x, float y, float w, float h, float s1, float t1, float s2, float t2,float a, qhandle_t hShader ); +#ifdef REND2_SP +void RE_LAGoggles(void); +void RE_Scissor(float x, float y, float w, float h); +#endif void RE_BeginFrame( stereoFrame_t stereoFrame ); void R_NewFrameSync(); void RE_EndFrame( int *frontEndMsec, int *backEndMsec ); @@ -3701,6 +3764,10 @@ void RE_TakeVideoFrame( int width, int height, byte *captureBuffer, byte *encodeBuffer, qboolean motionJpeg ); // tr_ghoul2.cpp +#ifdef REND2_SP +void Create_Matrix(const float* angle, mdxaBone_t* matrix); +void G2_SetSurfaceOnOffFromSkin(CGhoul2Info *ghlInfo, qhandle_t renderSkin); //tr_ghoul2.cpp +#endif void Mat3x4_Multiply(mdxaBone_t *out, const mdxaBone_t *in2, const mdxaBone_t *in); void Mat3x4_Scale( mdxaBone_t *result, const mdxaBone_t *lhs, const float scale ); void Mat3x4_Lerp( diff --git a/codemp/rd-rend2/tr_main.cpp b/shared/rd-rend2/tr_main.cpp similarity index 96% rename from codemp/rd-rend2/tr_main.cpp rename to shared/rd-rend2/tr_main.cpp index 7f8e5e10fb..cabcc4e241 100644 --- a/codemp/rd-rend2/tr_main.cpp +++ b/shared/rd-rend2/tr_main.cpp @@ -25,9 +25,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "tr_weather.h" #include // memcpy - +#ifndef REND2_SP #include "ghoul2/g2_local.h" - +#endif trGlobals_t tr; static float s_flipMatrix[16] = { @@ -820,10 +820,12 @@ static void R_SetFarClip( viewParms_t *viewParms, const trRefdef_t *refdef ) if (refdef != NULL) { if (refdef->rdflags & RDF_NOWORLDMODEL) { +#ifndef REND2_SP // override the zfar then if (refdef->rdflags & RDF_AUTOMAP) viewParms->zFar = 32768.0f; else +#endif viewParms->zFar = 2048.0f; return; } @@ -1652,29 +1654,67 @@ See if a sprite is inside a fog volume ================= */ int R_SpriteFogNum( trRefEntity_t *ent ) { - int i, j; + int i; + float frameRadius; fog_t *fog; + vec3_t localOrigin; if ( tr.refdef.rdflags & RDF_NOWORLDMODEL ) { return 0; } - for ( i = 1 ; i < tr.world->numfogs ; i++ ) { + VectorCopy(ent->e.origin, localOrigin); + frameRadius = ent->e.radius; +#ifndef REND2_SP + int j; + for (i = 1; i < tr.world->numfogs; i++) { fog = &tr.world->fogs[i]; - for ( j = 0 ; j < 3 ; j++ ) { - if ( ent->e.origin[j] - ent->e.radius >= fog->bounds[1][j] ) { + for (j = 0; j < 3; j++) { + if (localOrigin[j] - frameRadius >= fog->bounds[1][j]) { break; } - if ( ent->e.origin[j] + ent->e.radius <= fog->bounds[0][j] ) { + if (localOrigin[j] + frameRadius <= fog->bounds[0][j]) { break; } } - if ( j == 3 ) { + if (j == 3) { return i; } } - return 0; +#else + int partialFog = 0; + for (i = 1; i < tr.world->numfogs; i++) { + fog = &tr.world->fogs[i]; + if (localOrigin[0] - frameRadius >= fog->bounds[0][0] + && localOrigin[0] + frameRadius <= fog->bounds[1][0] + && localOrigin[1] - frameRadius >= fog->bounds[0][1] + && localOrigin[1] + frameRadius <= fog->bounds[1][1] + && localOrigin[2] - frameRadius >= fog->bounds[0][2] + && localOrigin[2] + frameRadius <= fog->bounds[1][2]) + {//totally inside it + return i; + break; + } + if ((localOrigin[0] - frameRadius >= fog->bounds[0][0] && localOrigin[1] - frameRadius >= fog->bounds[0][1] && localOrigin[2] - frameRadius >= fog->bounds[0][2] && + localOrigin[0] - frameRadius <= fog->bounds[1][0] && localOrigin[1] - frameRadius <= fog->bounds[1][1] && localOrigin[2] - frameRadius <= fog->bounds[1][2]) || + (localOrigin[0] + frameRadius >= fog->bounds[0][0] && localOrigin[1] + frameRadius >= fog->bounds[0][1] && localOrigin[2] + frameRadius >= fog->bounds[0][2] && + localOrigin[0] + frameRadius <= fog->bounds[1][0] && localOrigin[1] + frameRadius <= fog->bounds[1][1] && localOrigin[2] + frameRadius <= fog->bounds[1][2])) + {//partially inside it + //if (tr.refdef.fogIndex == i || R_FogParmsMatch(tr.refdef.fogIndex, i)) + //{//take new one only if it's the same one that the viewpoint is in + // return i; + // break; + //} + //else + if (!partialFog) + {//first partialFog + partialFog = i; + } + } + } + return partialFog; +#endif } /* @@ -1741,7 +1781,9 @@ static void R_RadixSort( drawSurf_t *source, int size ) bool R_IsPostRenderEntity ( const trRefEntity_t *refEntity ) { return (refEntity->e.renderfx & RF_DISTORTION) || +#ifndef REND2_SP (refEntity->e.renderfx & RF_FORCEPOST) || +#endif (refEntity->e.renderfx & RF_FORCE_ENT_ALPHA); } @@ -1786,12 +1828,17 @@ void R_AddDrawSurf( { int index; drawSurf_t *surf; - +#ifndef REND2_SP if (tr.refdef.rdflags & RDF_NOFOG) { fogIndex = 0; } - +#else + if (tr.refdef.doLAGoggles) + { + fogIndex = tr.world->numfogs; + } +#endif if ( (shader->surfaceFlags & SURF_FORCESIGHT) && !(tr.refdef.rdflags & RDF_ForceSightOn) ) { //if shader is only seen with ForceSight and we don't have ForceSight on, then don't draw return; @@ -1872,6 +1919,8 @@ static void R_AddEntitySurface(const trRefdef_t *refdef, trRefEntity_t *ent, int case RT_ELECTRICITY: case RT_LINE: case RT_ORIENTEDLINE: + case RT_LATHE: + case RT_CLOUDS: case RT_CYLINDER: case RT_SABER_GLOW: // self blood sprites, talk balloons, etc should not be drawn in the primary @@ -2252,7 +2301,6 @@ void R_SetupViewParmsForOrthoRendering( void R_SetupPshadowMaps(trRefdef_t *refdef) { - viewParms_t shadowParms; int i; // first, make a list of shadows @@ -2260,7 +2308,7 @@ void R_SetupPshadowMaps(trRefdef_t *refdef) { trRefEntity_t *ent = &refdef->entities[i]; - if((ent->e.renderfx & (RF_FIRST_PERSON | RF_NOSHADOW))) + if((ent->e.renderfx & (RF_FIRST_PERSON | RF_NOSHADOW | RF_DEPTHHACK))) continue; //if((ent->e.renderfx & RF_THIRD_PERSON)) @@ -2290,6 +2338,13 @@ void R_SetupPshadowMaps(trRefdef_t *refdef) { if (ent->e.ghoul2 && G2API_HaveWeGhoul2Models(*((CGhoul2Info_v *)ent->e.ghoul2))) { + shader_t *cust_shader = nullptr; + if (ent->e.customShader) + { + cust_shader = R_GetShaderByHandle(ent->e.customShader); + if (cust_shader->sort != SS_OPAQUE) + continue; + } // scale the radius if needed float largestScale = ent->e.modelScale[0]; if (ent->e.modelScale[1] > largestScale) @@ -2488,7 +2543,7 @@ void R_SetupViewParms(const trRefdef_t *refdef) tr.viewParms.viewportX = refdef->x; // Shoud be just refef->y but this flips the menu orientation for models, so its actually needed like this - if (!tr.world) + if (!tr.world || refdef->rdflags & RDF_NOWORLDMODEL) tr.viewParms.viewportY = glConfig.vidHeight - (refdef->y + refdef->height); else tr.viewParms.viewportY = refdef->y; @@ -2510,7 +2565,7 @@ void R_SetupViewParms(const trRefdef_t *refdef) R_RotateForViewer(&tr.viewParms.world, &tr.viewParms); R_SetupProjection(&tr.viewParms, tr.viewParms.zNear, tr.viewParms.zFar, qtrue); - if (tr.world) + if (tr.world && !(refdef->rdflags & RDF_NOWORLDMODEL)) { R_MarkLeaves(); @@ -2527,7 +2582,7 @@ void R_SetupViewParms(const trRefdef_t *refdef) qboolean R_AddPortalView(const trRefdef_t *refdef) { - if (!tr.world) + if (!tr.world || refdef->rdflags & RDF_NOWORLDMODEL) return qfalse; for (int i = 0; i < tr.world->numWorldSurfaces; i++) @@ -2639,7 +2694,9 @@ void R_GatherFrameViews(trRefdef_t *refdef) { int mainFlags = 0; // skyportal view - if (tr.world && tr.world->skyboxportal) + if (tr.world && + tr.world->skyboxportal && + !(refdef->rdflags & RDF_NOWORLDMODEL)) { tr.viewCount++; tr.viewParms = tr.skyPortalParms; @@ -2664,7 +2721,7 @@ void R_GatherFrameViews(trRefdef_t *refdef) } VectorCopy(refdef->vieworg, tr.viewParms.pvsOrigin); - if (tr.world) + if (tr.world && !(refdef->rdflags & RDF_NOWORLDMODEL)) R_MarkLeaves(); if (!(refdef->rdflags & RDF_NOWORLDMODEL)) diff --git a/codemp/rd-rend2/tr_marks.cpp b/shared/rd-rend2/tr_marks.cpp similarity index 100% rename from codemp/rd-rend2/tr_marks.cpp rename to shared/rd-rend2/tr_marks.cpp diff --git a/codemp/rd-rend2/tr_mesh.cpp b/shared/rd-rend2/tr_mesh.cpp similarity index 82% rename from codemp/rd-rend2/tr_mesh.cpp rename to shared/rd-rend2/tr_mesh.cpp index 503c7a9b29..d68082088e 100644 --- a/codemp/rd-rend2/tr_mesh.cpp +++ b/shared/rd-rend2/tr_mesh.cpp @@ -156,6 +156,30 @@ static int R_CullModel( mdvModel_t *model, trRefEntity_t *ent ) { } } +/* +================= +RE_GetModelBounds + + Returns the bounds of the current model + (qhandle_t)hModel and (int)frame need to be set +================= +*/ + +void RE_GetModelBounds(refEntity_t *refEnt, vec3_t bounds1, vec3_t bounds2) +{ + mdvFrame_t *frame; + model_t *model; + + assert(refEnt); + + model = R_GetModelByHandle(refEnt->hModel); + assert(model); + frame = &model->data.mdv[0]->frames[refEnt->frame]; + assert(frame); + + VectorCopy(frame->bounds[0], bounds1); + VectorCopy(frame->bounds[1], bounds2); +} /* ================= @@ -244,7 +268,8 @@ R_ComputeFogNum ================= */ int R_ComputeFogNum( mdvModel_t *model, trRefEntity_t *ent ) { - int i, j; + int i; + float frameRadius; fog_t *fog; mdvFrame_t *mdvFrame; vec3_t localOrigin; @@ -256,13 +281,16 @@ int R_ComputeFogNum( mdvModel_t *model, trRefEntity_t *ent ) { // FIXME: non-normalized axis issues mdvFrame = model->frames + ent->e.frame; VectorAdd( ent->e.origin, mdvFrame->localOrigin, localOrigin ); + frameRadius = mdvFrame->radius; +#ifndef REND2_SP + int j; for ( i = 1 ; i < tr.world->numfogs ; i++ ) { fog = &tr.world->fogs[i]; for ( j = 0 ; j < 3 ; j++ ) { - if ( localOrigin[j] - mdvFrame->radius >= fog->bounds[1][j] ) { + if ( localOrigin[j] - frameRadius >= fog->bounds[1][j] ) { break; } - if ( localOrigin[j] + mdvFrame->radius <= fog->bounds[0][j] ) { + if ( localOrigin[j] + frameRadius <= fog->bounds[0][j] ) { break; } } @@ -270,8 +298,40 @@ int R_ComputeFogNum( mdvModel_t *model, trRefEntity_t *ent ) { return i; } } - return 0; +#else + int partialFog = 0; + for (i = 1; i < tr.world->numfogs; i++) { + fog = &tr.world->fogs[i]; + if (localOrigin[0] - frameRadius >= fog->bounds[0][0] + && localOrigin[0] + frameRadius <= fog->bounds[1][0] + && localOrigin[1] - frameRadius >= fog->bounds[0][1] + && localOrigin[1] + frameRadius <= fog->bounds[1][1] + && localOrigin[2] - frameRadius >= fog->bounds[0][2] + && localOrigin[2] + frameRadius <= fog->bounds[1][2]) + {//totally inside it + return i; + break; + } + if ((localOrigin[0] - frameRadius >= fog->bounds[0][0] && localOrigin[1] - frameRadius >= fog->bounds[0][1] && localOrigin[2] - frameRadius >= fog->bounds[0][2] && + localOrigin[0] - frameRadius <= fog->bounds[1][0] && localOrigin[1] - frameRadius <= fog->bounds[1][1] && localOrigin[2] - frameRadius <= fog->bounds[1][2]) || + (localOrigin[0] + frameRadius >= fog->bounds[0][0] && localOrigin[1] + frameRadius >= fog->bounds[0][1] && localOrigin[2] + frameRadius >= fog->bounds[0][2] && + localOrigin[0] + frameRadius <= fog->bounds[1][0] && localOrigin[1] + frameRadius <= fog->bounds[1][1] && localOrigin[2] + frameRadius <= fog->bounds[1][2])) + {//partially inside it + //if (tr.refdef.fogIndex == i || R_FogParmsMatch(tr.refdef.fogIndex, i)) + //{//take new one only if it's the same one that the viewpoint is in + // return i; + // break; + //} + //else + if (!partialFog) + {//first partialFog + partialFog = i; + } + } + } + return partialFog; +#endif } /* diff --git a/codemp/rd-rend2/tr_model.cpp b/shared/rd-rend2/tr_model.cpp similarity index 95% rename from codemp/rd-rend2/tr_model.cpp rename to shared/rd-rend2/tr_model.cpp index 3856f0872a..1d4a8a9e5f 100644 --- a/codemp/rd-rend2/tr_model.cpp +++ b/shared/rd-rend2/tr_model.cpp @@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "tr_local.h" #include "tr_cache.h" #include +#include #define LL(x) x=LittleLong(x) @@ -247,7 +248,7 @@ model_t *R_AllocModel( void ) { return NULL; } - mod = (model_t *)ri.Hunk_Alloc( sizeof( *tr.models[tr.numModels] ), h_low ); + mod = (model_t *)Hunk_Alloc( sizeof( *tr.models[tr.numModels] ), h_low ); mod->index = tr.numModels; tr.models[tr.numModels] = mod; tr.numModels++; @@ -268,7 +269,7 @@ static qhandle_t RE_RegisterBSP(const char *name) } char bspModelIdent[MAX_QPATH]; - Com_sprintf(bspModelIdent, sizeof(bspModelIdent), "*%d-0", bspIndex); + Com_sprintf(bspModelIdent, sizeof(bspModelIdent), "*%d-0", bspIndex+1); qhandle_t modelHandle = CModelCache->GetModelHandle(bspModelIdent); if (modelHandle == -1) @@ -315,6 +316,7 @@ qhandle_t RE_RegisterModel( const char *name ) { if( ( hModel = CModelCache->GetModelHandle( name ) ) != -1 ) return hModel; +#ifndef REND2_SP if ( name[0] == '*' ) { if ( strcmp (name, "*default.gla") != 0 ) @@ -322,6 +324,7 @@ qhandle_t RE_RegisterModel( const char *name ) { return 0; } } +#endif if( name[0] == '#' ) { @@ -522,7 +525,7 @@ qboolean R_LoadMDXM_Server( model_t *mod, void *buffer, const char *mod_name, qb qboolean bAlreadyFound = qfalse; mdxm = (mdxmHeader_t*)CModelCache->Allocate( size, buffer, mod_name, &bAlreadyFound, TAG_MODEL_GLM ); - mod->data.glm = (mdxmData_t *)ri.Hunk_Alloc (sizeof (mdxmData_t), h_low); + mod->data.glm = (mdxmData_t *)Hunk_Alloc (sizeof (mdxmData_t), h_low); mod->data.glm->header = mdxm; assert(bAlreadyCached == bAlreadyFound); // I should probably eliminate 'bAlreadyFound', but wtf? @@ -743,7 +746,11 @@ qhandle_t RE_RegisterServerModel( const char *name ) { if (!r_noServerGhoul2) { //keep it from choking when it gets to these checks in the g2 code. Registering all r_ cvars for the server would be a Bad Thing though. +#ifndef REND2_SP r_noServerGhoul2 = ri.Cvar_Get( "r_noserverghoul2", "0", 0, ""); +#else + r_noServerGhoul2 = ri.Cvar_Get("r_noghoul2", "0", 0); +#endif } if ( !name || !name[0] ) { @@ -859,10 +866,10 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN mod->type = MOD_MESH; size = LittleLong(md3Model->ofsEnd); mod->dataSize += size; - //mdvModel = mod->mdv[lod] = (mdvModel_t *)ri.Hunk_Alloc(sizeof(mdvModel_t), h_low); + //mdvModel = mod->mdv[lod] = (mdvModel_t *)Hunk_Alloc(sizeof(mdvModel_t), h_low); qboolean bAlreadyFound = qfalse; md3Model = (md3Header_t *)CModelCache->Allocate(size, buffer, modName, &bAlreadyFound, TAG_MODEL_MD3); - mdvModel = mod->data.mdv[lod] = (mdvModel_t *)ri.Hunk_Alloc(sizeof(*mdvModel), h_low); + mdvModel = mod->data.mdv[lod] = (mdvModel_t *)Hunk_Alloc(sizeof(*mdvModel), h_low); // Com_Memcpy(mod->md3[lod], buffer, LittleLong(md3Model->ofsEnd)); if( !bAlreadyFound ) @@ -890,7 +897,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN // swap all the frames mdvModel->numFrames = md3Model->numFrames; - mdvModel->frames = frame = (mdvFrame_t *)ri.Hunk_Alloc(sizeof(*frame) * md3Model->numFrames, h_low); + mdvModel->frames = frame = (mdvFrame_t *)Hunk_Alloc(sizeof(*frame) * md3Model->numFrames, h_low); md3Frame = (md3Frame_t *) ((byte *) md3Model + md3Model->ofsFrames); for(i = 0; i < md3Model->numFrames; i++, frame++, md3Frame++) @@ -906,7 +913,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN // swap all the tags mdvModel->numTags = md3Model->numTags; - mdvModel->tags = tag = (mdvTag_t *)ri.Hunk_Alloc(sizeof(*tag) * (md3Model->numTags * md3Model->numFrames), h_low); + mdvModel->tags = tag = (mdvTag_t *)Hunk_Alloc(sizeof(*tag) * (md3Model->numTags * md3Model->numFrames), h_low); md3Tag = (md3Tag_t *) ((byte *) md3Model + md3Model->ofsTags); for(i = 0; i < md3Model->numTags * md3Model->numFrames; i++, tag++, md3Tag++) @@ -921,7 +928,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN } - mdvModel->tagNames = tagName = (mdvTagName_t *)ri.Hunk_Alloc(sizeof(*tagName) * (md3Model->numTags), h_low); + mdvModel->tagNames = tagName = (mdvTagName_t *)Hunk_Alloc(sizeof(*tagName) * (md3Model->numTags), h_low); md3Tag = (md3Tag_t *) ((byte *) md3Model + md3Model->ofsTags); for(i = 0; i < md3Model->numTags; i++, tagName++, md3Tag++) @@ -931,7 +938,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN // swap all the surfaces mdvModel->numSurfaces = md3Model->numSurfaces; - mdvModel->surfaces = surf = (mdvSurface_t *)ri.Hunk_Alloc(sizeof(*surf) * md3Model->numSurfaces, h_low); + mdvModel->surfaces = surf = (mdvSurface_t *)Hunk_Alloc(sizeof(*surf) * md3Model->numSurfaces, h_low); md3Surf = (md3Surface_t *) ((byte *) md3Model + md3Model->ofsSurfaces); for(i = 0; i < md3Model->numSurfaces; i++) @@ -985,7 +992,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN // register the shaders surf->numShaderIndexes = md3Surf->numShaders; - surf->shaderIndexes = shaderIndex = (int *)ri.Hunk_Alloc(sizeof(*shaderIndex) * md3Surf->numShaders, h_low); + surf->shaderIndexes = shaderIndex = (int *)Hunk_Alloc(sizeof(*shaderIndex) * md3Surf->numShaders, h_low); md3Shader = (md3Shader_t *) ((byte *) md3Surf + md3Surf->ofsShaders); for(j = 0; j < md3Surf->numShaders; j++, shaderIndex++, md3Shader++) @@ -1005,7 +1012,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN // swap all the triangles surf->numIndexes = md3Surf->numTriangles * 3; - surf->indexes = tri = (glIndex_t *)ri.Hunk_Alloc(sizeof(*tri) * 3 * md3Surf->numTriangles, h_low); + surf->indexes = tri = (glIndex_t *)Hunk_Alloc(sizeof(*tri) * 3 * md3Surf->numTriangles, h_low); md3Tri = (md3Triangle_t *) ((byte *) md3Surf + md3Surf->ofsTriangles); for(j = 0; j < md3Surf->numTriangles; j++, tri += 3, md3Tri++) @@ -1017,7 +1024,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN // swap all the XyzNormals surf->numVerts = md3Surf->numVerts; - surf->verts = v = (mdvVertex_t *)ri.Hunk_Alloc(sizeof(*v) * (md3Surf->numVerts * md3Surf->numFrames), h_low); + surf->verts = v = (mdvVertex_t *)Hunk_Alloc(sizeof(*v) * (md3Surf->numVerts * md3Surf->numFrames), h_low); md3xyz = (md3XyzNormal_t *) ((byte *) md3Surf + md3Surf->ofsXyzNormals); for(j = 0; j < md3Surf->numVerts * md3Surf->numFrames; j++, md3xyz++, v++) @@ -1046,7 +1053,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN } // swap all the ST - surf->st = st = (mdvSt_t *)ri.Hunk_Alloc(sizeof(*st) * md3Surf->numVerts, h_low); + surf->st = st = (mdvSt_t *)Hunk_Alloc(sizeof(*st) * md3Surf->numVerts, h_low); md3st = (md3St_t *) ((byte *) md3Surf + md3Surf->ofsSt); for(j = 0; j < md3Surf->numVerts; j++, md3st++, st++) @@ -1064,7 +1071,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN srfVBOMDVMesh_t *vboSurf; mdvModel->numVBOSurfaces = mdvModel->numSurfaces; - mdvModel->vboSurfaces = (srfVBOMDVMesh_t *)ri.Hunk_Alloc(sizeof(*mdvModel->vboSurfaces) * mdvModel->numSurfaces, h_low); + mdvModel->vboSurfaces = (srfVBOMDVMesh_t *)Hunk_Alloc(sizeof(*mdvModel->vboSurfaces) * mdvModel->numSurfaces, h_low); vboSurf = mdvModel->vboSurfaces; surf = mdvModel->surfaces; @@ -1082,8 +1089,8 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN int numIndexes = 0; // +1 to add total vertex count - int *baseVertexes = (int *)ri.Hunk_AllocateTempMemory(sizeof(int) * (mdvModel->numSurfaces + 1)); - int *indexOffsets = (int *)ri.Hunk_AllocateTempMemory(sizeof(int) * mdvModel->numSurfaces); + int *baseVertexes = (int *)Hunk_AllocateTempMemory(sizeof(int) * (mdvModel->numSurfaces + 1)); + int *indexOffsets = (int *)Hunk_AllocateTempMemory(sizeof(int) * mdvModel->numSurfaces); // Calculate the required size of the vertex buffer. for (int n = 0; n < mdvModel->numSurfaces; n++, surf++) @@ -1102,7 +1109,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN dataSize += numVerts * sizeof(*tangents); // Allocate and write to memory - data = (byte *)ri.Hunk_AllocateTempMemory(dataSize); + data = (byte *)Hunk_AllocateTempMemory(dataSize); ofsPosition = stride; verts = (vec3_t *)(data + ofsPosition); @@ -1121,13 +1128,13 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN stride += sizeof(*tangents); // Fill in the index buffer and compute tangents - glIndex_t *indices = (glIndex_t *)ri.Hunk_AllocateTempMemory(sizeof(glIndex_t) * numIndexes); + glIndex_t *indices = (glIndex_t *)Hunk_AllocateTempMemory(sizeof(glIndex_t) * numIndexes); glIndex_t *index = indices; surf = mdvModel->surfaces; for (i = 0; i < mdvModel->numSurfaces; i++, surf++) { - uint32_t *tangentsf = (uint32_t *)ri.Hunk_AllocateTempMemory(sizeof(uint32_t) * surf->numVerts); + uint32_t *tangentsf = (uint32_t *)Hunk_AllocateTempMemory(sizeof(uint32_t) * surf->numVerts); R_CalcMikkTSpaceMD3Surface( surf->numIndexes / 3, surf->verts, @@ -1153,7 +1160,7 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN normals = (uint32_t *)((byte *)normals + stride); tangents = (uint32_t *)((byte *)tangents + stride); } - ri.Hunk_FreeTempMemory(tangentsf); + Hunk_FreeTempMemory(tangentsf); st = surf->st; for (j = 0; j < surf->numVerts; j++, st++) { @@ -1169,8 +1176,8 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN VBO_t *vbo = R_CreateVBO(data, dataSize, VBO_USAGE_STATIC); IBO_t *ibo = R_CreateIBO((byte *)indices, sizeof(glIndex_t) * numIndexes, VBO_USAGE_STATIC); - ri.Hunk_FreeTempMemory(data); - ri.Hunk_FreeTempMemory(indices); + Hunk_FreeTempMemory(data); + Hunk_FreeTempMemory(indices); vbo->offsets[ATTR_INDEX_POSITION] = ofsPosition; vbo->offsets[ATTR_INDEX_NORMAL] = ofsNormals; @@ -1203,8 +1210,8 @@ static qboolean R_LoadMD3(model_t * mod, int lod, void *buffer, const char *modN vboSurf->numIndexes = surf->numIndexes; } - ri.Hunk_FreeTempMemory(indexOffsets); - ri.Hunk_FreeTempMemory(baseVertexes); + Hunk_FreeTempMemory(indexOffsets); + Hunk_FreeTempMemory(baseVertexes); } return qtrue; @@ -1273,7 +1280,7 @@ static qboolean R_LoadMDR( model_t *mod, void *buffer, int filesize, const char } mod->dataSize += size; - mod->data.mdr = mdr = (mdrHeader_t*)ri.Hunk_Alloc( size, h_low ); + mod->data.mdr = mdr = (mdrHeader_t*)Hunk_Alloc( size, h_low ); // Copy all the values over from the file and fix endian issues in the process, if necessary. @@ -1585,7 +1592,11 @@ void RE_BeginRegistration( glconfig_t *glconfigOut ) { void R_SVModelInit() { - R_ModelInit(); + // Vanilla SP setups textures, shaders and models only + // Rend2 requires gpu buffer access for shaders already so, just do renderer setup already + // Shouldn't hurt to do so in MP too + // R_Init now makes sure its only doing its thing once unless everything is destructed again + R_Init(); } /* diff --git a/codemp/rd-rend2/tr_model_iqm.cpp b/shared/rd-rend2/tr_model_iqm.cpp similarity index 99% rename from codemp/rd-rend2/tr_model_iqm.cpp rename to shared/rd-rend2/tr_model_iqm.cpp index 3d6e007842..6af9a6a562 100644 --- a/codemp/rd-rend2/tr_model_iqm.cpp +++ b/shared/rd-rend2/tr_model_iqm.cpp @@ -483,7 +483,7 @@ qboolean R_LoadIQM( model_t *mod, void *buffer, int filesize, const char *mod_na } mod->type = MOD_IQM; - iqmData = (iqmData_t *)ri.Hunk_Alloc( size, h_low ); + iqmData = (iqmData_t *)Hunk_Alloc( size, h_low ); mod->data.iqm = iqmData; // fill header diff --git a/codemp/rd-rend2/tr_postprocess.cpp b/shared/rd-rend2/tr_postprocess.cpp similarity index 99% rename from codemp/rd-rend2/tr_postprocess.cpp rename to shared/rd-rend2/tr_postprocess.cpp index 35a8ba29d8..b4c2784ca9 100644 --- a/codemp/rd-rend2/tr_postprocess.cpp +++ b/shared/rd-rend2/tr_postprocess.cpp @@ -491,8 +491,7 @@ void RB_BloomDownscale(image_t *sourceImage, FBO_t *destFBO) FBO_Bind(destFBO); GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO); - - qglViewport(0, 0, destFBO->width, destFBO->height); + GL_SetViewportAndScissor(0, 0, destFBO->width, destFBO->height); qglClearBufferfv(GL_COLOR, 0, colorBlack); GLSL_BindProgram(&tr.dglowDownsample); @@ -515,8 +514,7 @@ void RB_BloomUpscale(FBO_t *sourceFBO, FBO_t *destFBO) FBO_Bind(destFBO); GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO); - - glViewport(0, 0, destFBO->width, destFBO->height); + GL_SetViewportAndScissor(0, 0, destFBO->width, destFBO->height); qglClearBufferfv(GL_COLOR, 0, colorBlack); GLSL_BindProgram(&tr.dglowUpsample); diff --git a/codemp/rd-rend2/tr_postprocess.h b/shared/rd-rend2/tr_postprocess.h similarity index 100% rename from codemp/rd-rend2/tr_postprocess.h rename to shared/rd-rend2/tr_postprocess.h diff --git a/codemp/rd-rend2/tr_scene.cpp b/shared/rd-rend2/tr_scene.cpp similarity index 95% rename from codemp/rd-rend2/tr_scene.cpp rename to shared/rd-rend2/tr_scene.cpp index 6835c305a3..058f6d5495 100644 --- a/codemp/rd-rend2/tr_scene.cpp +++ b/shared/rd-rend2/tr_scene.cpp @@ -91,8 +91,9 @@ Adds all the scene's polys into this view's drawsurf list */ void R_AddPolygonSurfaces( const trRefdef_t *refdef ) { srfPoly_t *poly; +#ifndef REND2_SP int fogMask = -((refdef->rdflags & RDF_NOFOG) == 0); - +#endif int i; for ( i = 0, poly = refdef->polys; i < refdef->numPolys ; i++, poly++ ) { shader_t *sh = R_GetShaderByHandle( poly->hShader ); @@ -100,7 +101,11 @@ void R_AddPolygonSurfaces( const trRefdef_t *refdef ) { (surfaceType_t *)poly, REFENTITYNUM_WORLD, sh, +#ifndef REND2_SP poly->fogIndex & fogMask, +#else + poly->fogIndex, +#endif qfalse, qfalse, 0 /* cubemapIndex */ ); @@ -113,6 +118,7 @@ RE_AddPolyToScene ===================== */ + void RE_AddPolyToScene( qhandle_t hShader, int numVerts, const polyVert_t *verts, int numPolys ) { srfPoly_t *poly; int i, j; @@ -205,7 +211,13 @@ void RE_AddRefEntityToScene( const refEntity_t *ent ) { } return; } - if ( (int)ent->reType < 0 || ent->reType >= RT_MAX_REF_ENTITY_TYPE ) { + + if (ent->reType == RT_ENT_CHAIN) + { //minirefents must die. + return; + } + + if ( (int)ent->reType < 0 || ent->reType >= RT_MAX_SP_REF_ENTITY_TYPE || ent->reType == RT_MAX_MP_REF_ENTITY_TYPE ) { ri.Error( ERR_DROP, "RE_AddRefEntityToScene: bad reType %i", ent->reType ); } @@ -218,6 +230,7 @@ void RE_AddRefEntityToScene( const refEntity_t *ent ) { r_numentities++; } +#ifndef REND2_SP /* ===================== RE_AddMiniRefEntityToScene @@ -235,7 +248,7 @@ void RE_AddMiniRefEntityToScene( const miniRefEntity_t *miniRefEnt ) { memcpy(&entity, miniRefEnt, sizeof(*miniRefEnt)); RE_AddRefEntityToScene(&entity); } - +#endif /* ===================== @@ -267,8 +280,10 @@ void RE_AddDynamicLightToScene( const vec3_t org, float intensity, float r, floa float maxValue = MAX(r, MAX(g, b)); if (maxValue > 1.0f) { + // Renderer expects normalized color, in sdr there was no problem VectorScale(dl->color, 1.0f / maxValue, dl->color); - dl->radius *= maxValue; + // Don't scale the radius + //dl->radius *= maxValue; } dl->radius = MIN(dl->radius, 65535.0f); } @@ -298,8 +313,6 @@ void RE_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, flo void RE_BeginScene(const refdef_t *fd) { - Com_Memcpy( tr.refdef.text, fd->text, sizeof( tr.refdef.text ) ); - tr.refdef.x = fd->x; tr.refdef.y = fd->y; tr.refdef.width = fd->width; @@ -505,6 +518,15 @@ void RE_EndScene() r_firstScenePoly = r_numpolys; tr.skyPortalEntities = 0; tr.numCachedViewParms = 0; +#ifdef REND2_SP + tr.refdef.doLAGoggles = false; + tr.refdef.doFullbright = false; +#endif + backEndData->currentFrame->currentScene++; + if (backEndData->currentFrame->currentScene > MAX_SCENES) + { + ri.Error(ERR_DROP, "Tried to render to many subscenes per frame"); + } } /* diff --git a/codemp/rd-rend2/tr_shade.cpp b/shared/rd-rend2/tr_shade.cpp similarity index 93% rename from codemp/rd-rend2/tr_shade.cpp rename to shared/rd-rend2/tr_shade.cpp index 062cb6166a..baafb31dcd 100644 --- a/codemp/rd-rend2/tr_shade.cpp +++ b/shared/rd-rend2/tr_shade.cpp @@ -692,7 +692,8 @@ void RB_FillDrawCommand( static UniformBlockBinding GetCameraBlockUniformBinding( const trRefEntity_t *refEntity) { - const GLuint currentFrameUbo = backEndData->currentFrame->ubo; + const byte currentFrameScene = backEndData->currentFrame->currentScene; + const GLuint currentFrameUbo = backEndData->currentFrame->ubo[currentFrameScene]; UniformBlockBinding binding = {}; binding.block = UNIFORM_BLOCK_CAMERA; @@ -716,7 +717,8 @@ static UniformBlockBinding GetCameraBlockUniformBinding( static UniformBlockBinding GetLightsBlockUniformBinding() { - const GLuint currentFrameUbo = backEndData->currentFrame->ubo; + const byte currentFrameScene = backEndData->currentFrame->currentScene; + const GLuint currentFrameUbo = backEndData->currentFrame->ubo[currentFrameScene]; UniformBlockBinding binding = {}; binding.block = UNIFORM_BLOCK_LIGHTS; @@ -735,7 +737,8 @@ static UniformBlockBinding GetLightsBlockUniformBinding() static UniformBlockBinding GetSceneBlockUniformBinding() { - const GLuint currentFrameUbo = backEndData->currentFrame->ubo; + const byte currentFrameScene = backEndData->currentFrame->currentScene; + const GLuint currentFrameUbo = backEndData->currentFrame->ubo[currentFrameScene]; UniformBlockBinding binding = {}; binding.block = UNIFORM_BLOCK_SCENE; @@ -754,7 +757,8 @@ static UniformBlockBinding GetSceneBlockUniformBinding() static UniformBlockBinding GetFogsBlockUniformBinding() { - const GLuint currentFrameUbo = backEndData->currentFrame->ubo; + const byte currentFrameScene = backEndData->currentFrame->currentScene; + const GLuint currentFrameUbo = backEndData->currentFrame->ubo[currentFrameScene]; UniformBlockBinding binding = {}; binding.block = UNIFORM_BLOCK_FOGS; @@ -774,7 +778,8 @@ static UniformBlockBinding GetFogsBlockUniformBinding() static UniformBlockBinding GetEntityBlockUniformBinding( const trRefEntity_t *refEntity) { - const GLuint currentFrameUbo = backEndData->currentFrame->ubo; + const byte currentFrameScene = backEndData->currentFrame->currentScene; + const GLuint currentFrameUbo = backEndData->currentFrame->ubo[currentFrameScene]; UniformBlockBinding binding = {}; binding.block = UNIFORM_BLOCK_ENTITY; @@ -808,7 +813,8 @@ static UniformBlockBinding GetEntityBlockUniformBinding( static UniformBlockBinding GetBonesBlockUniformBinding( const trRefEntity_t *refEntity) { - const GLuint currentFrameUbo = backEndData->currentFrame->ubo; + const byte currentFrameScene = backEndData->currentFrame->currentScene; + const GLuint currentFrameUbo = backEndData->currentFrame->ubo[currentFrameScene]; UniformBlockBinding binding = {}; binding.ubo = currentFrameUbo; binding.block = UNIFORM_BLOCK_BONES; @@ -828,7 +834,8 @@ static UniformBlockBinding GetBonesBlockUniformBinding( static UniformBlockBinding GetShaderInstanceBlockUniformBinding( const trRefEntity_t *refEntity, const shader_t *shader) { - const GLuint currentFrameUbo = backEndData->currentFrame->ubo; + const byte currentFrameScene = backEndData->currentFrame->currentScene; + const GLuint currentFrameUbo = backEndData->currentFrame->ubo[currentFrameScene]; UniformBlockBinding binding = {}; binding.ubo = tr.shaderInstanceUbo; binding.block = UNIFORM_BLOCK_SHADER_INSTANCE; @@ -864,13 +871,14 @@ static void DrawTris(shaderCommands_t *input, const VertexArraysProperties *vert { index |= GENERICDEF_USE_DEFORM_VERTEXES; } -#ifdef REND2_SP +#ifdef REND2_SP_MD3 if (glState.vertexAnimation) { index |= GENERICDEF_USE_VERTEX_ANIMATION; } + else #endif // REND2_SP - else if (glState.skeletalAnimation) + if (glState.skeletalAnimation) { index |= GENERICDEF_USE_SKELETAL_ANIMATION; } @@ -897,7 +905,7 @@ static void DrawTris(shaderCommands_t *input, const VertexArraysProperties *vert uniformDataWriter.SetUniformVec4(UNIFORM_VERTCOLOR, vertColor); DrawItem item = {}; - item.renderState.stateBits = GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE | GLS_POLYGON_OFFSET_FILL; + item.renderState.stateBits = GLS_POLYMODE_LINE | GLS_DEPTHTEST_DISABLE; item.renderState.cullType = RB_GetCullType(&backEnd.viewParms, backEnd.currentEntity, input->shader->cullType); item.renderState.depthRange = RB_GetDepthRange(backEnd.currentEntity, input->shader); item.program = sp; @@ -1037,11 +1045,12 @@ static void RB_FogPass( shaderCommands_t *input, const VertexArraysProperties *v if (input->shader->numDeforms && !ShaderRequiresCPUDeforms(input->shader)) shaderBits |= FOGDEF_USE_DEFORM_VERTEXES; -#ifdef REND2_SP +#ifdef REND2_SP_MD3 if (glState.vertexAnimation) shaderBits |= FOGDEF_USE_VERTEX_ANIMATION; + else #endif // REND2_SP - else if (glState.skeletalAnimation) + if (glState.skeletalAnimation) shaderBits |= FOGDEF_USE_SKELETAL_ANIMATION; if (tr.world && tr.world->globalFog && @@ -1049,9 +1058,9 @@ static void RB_FogPass( shaderCommands_t *input, const VertexArraysProperties *v input->shader->sort != SS_FOG) shaderBits |= FOGDEF_USE_FALLBACK_GLOBAL_FOG; - if (input->numPasses > 0) + /*if (input->numPasses > 0) if (input->xstages[0]->alphaTestType != ALPHA_TEST_NONE) - shaderBits |= FOGDEF_USE_ALPHA_TEST; + shaderBits |= FOGDEF_USE_ALPHA_TEST;*/ shaderProgram_t *sp = tr.fogShader + shaderBits; @@ -1153,7 +1162,7 @@ static void RB_FogPass( shaderCommands_t *input, const VertexArraysProperties *v static unsigned int RB_CalcShaderVertexAttribs( const shader_t *shader ) { unsigned int vertexAttribs = shader->vertexAttribs; -#ifdef REND2_SP +#ifdef REND2_SP_MD3 if(glState.vertexAnimation) { //vertexAttribs &= ~ATTR_COLOR; @@ -1186,13 +1195,14 @@ static shaderProgram_t *SelectShaderProgram( int stageIndex, shaderStage_t *stag { index |= REFRACTIONDEF_USE_DEFORM_VERTEXES; } -#ifdef REND2_SP +#ifdef REND2_SP_MD3 if (glState.vertexAnimation) { index |= REFRACTIONDEF_USE_VERTEX_ANIMATION; } + else #endif // REND2_SP - else if (glState.skeletalAnimation) + if (glState.skeletalAnimation) { index |= REFRACTIONDEF_USE_SKELETAL_ANIMATION; } @@ -1200,7 +1210,7 @@ static shaderProgram_t *SelectShaderProgram( int stageIndex, shaderStage_t *stag if (stage->bundle[0].tcGen != TCGEN_TEXTURE || (stage->bundle[0].numTexMods)) index |= REFRACTIONDEF_USE_TCGEN_AND_TCMOD; - if (!useAlphaTestGE192) + /*if (!useAlphaTestGE192) { if (stage->alphaTestType != ALPHA_TEST_NONE) index |= REFRACTIONDEF_USE_TCGEN_AND_TCMOD | REFRACTIONDEF_USE_ALPHA_TEST; @@ -1208,7 +1218,7 @@ static shaderProgram_t *SelectShaderProgram( int stageIndex, shaderStage_t *stag else { index |= REFRACTIONDEF_USE_ALPHA_TEST; - } + }*/ if (tr.hdrLighting == qtrue) index |= REFRACTIONDEF_USE_SRGB_TRANSFORM; @@ -1224,7 +1234,7 @@ static shaderProgram_t *SelectShaderProgram( int stageIndex, shaderStage_t *stag if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity) { -#ifdef REND2_SP +#ifdef REND2_SP_MD3 if (glState.vertexAnimation) { index |= LIGHTDEF_USE_VERTEX_ANIMATION; @@ -1237,7 +1247,7 @@ static shaderProgram_t *SelectShaderProgram( int stageIndex, shaderStage_t *stag } } - if ( !useAlphaTestGE192 ) + /*if ( !useAlphaTestGE192 ) { if (stage->alphaTestType != ALPHA_TEST_NONE) index |= LIGHTDEF_USE_ALPHA_TEST; @@ -1245,7 +1255,15 @@ static shaderProgram_t *SelectShaderProgram( int stageIndex, shaderStage_t *stag else { index |= LIGHTDEF_USE_ALPHA_TEST; - } + }*/ + + if (stage->bundle[0].tcGen != TCGEN_TEXTURE || (stage->bundle[0].numTexMods)) + index |= LIGHTDEF_USE_TCGEN_AND_TCMOD; + + // TODO: remove light vertex def and fix parallax usage on unlit stages like glow stages + if (stage->glslShaderIndex & LIGHTDEF_USE_PARALLAXMAP && + stage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK) + index |= LIGHTDEF_USE_PARALLAXMAP | LIGHTDEF_USE_LIGHT_VERTEX; result = &stage->glslShaderGroup[index]; backEnd.pc.c_lightallDraws++; @@ -1258,18 +1276,19 @@ static shaderProgram_t *SelectShaderProgram( int stageIndex, shaderStage_t *stag { index |= GENERICDEF_USE_DEFORM_VERTEXES; } -#ifdef REND2_SP +#ifdef REND2_SP_MD3 if (glState.vertexAnimation) { index |= GENERICDEF_USE_VERTEX_ANIMATION; } + else #endif // REND2_SP - else if (glState.skeletalAnimation) + if (glState.skeletalAnimation) { index |= GENERICDEF_USE_SKELETAL_ANIMATION; } - if ( !useAlphaTestGE192 ) + /*if ( !useAlphaTestGE192 ) { if (stage->alphaTestType != ALPHA_TEST_NONE) index |= GENERICDEF_USE_TCGEN_AND_TCMOD | GENERICDEF_USE_ALPHA_TEST; @@ -1277,7 +1296,7 @@ static shaderProgram_t *SelectShaderProgram( int stageIndex, shaderStage_t *stag else { index |= GENERICDEF_USE_ALPHA_TEST; - } + }*/ if (backEnd.currentEntity->e.renderfx & (RF_DISINTEGRATE1 | RF_DISINTEGRATE2)) index |= GENERICDEF_USE_RGBAGEN; @@ -1301,7 +1320,7 @@ static shaderProgram_t *SelectShaderProgram( int stageIndex, shaderStage_t *stag { if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity) { -#ifdef REND2_SP +#ifdef REND2_SP_MD3 if (glState.vertexAnimation) { index |= LIGHTDEF_USE_VERTEX_ANIMATION; @@ -1313,7 +1332,7 @@ static shaderProgram_t *SelectShaderProgram( int stageIndex, shaderStage_t *stag } } - if ( !useAlphaTestGE192 ) + /*if ( !useAlphaTestGE192 ) { if (stage->alphaTestType != ALPHA_TEST_NONE) index |= LIGHTDEF_USE_TCGEN_AND_TCMOD | LIGHTDEF_USE_ALPHA_TEST; @@ -1321,7 +1340,7 @@ static shaderProgram_t *SelectShaderProgram( int stageIndex, shaderStage_t *stag else { index |= LIGHTDEF_USE_ALPHA_TEST; - } + }*/ } result = &stage->glslShaderGroup[index]; @@ -1464,6 +1483,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input, const VertexArrays if ( backEnd.currentEntity->e.renderfx & RF_FORCE_ENT_ALPHA ) { stateBits = GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA; +#ifndef REND2_SP if ( backEnd.currentEntity->e.renderfx & RF_ALPHA_DEPTH ) { // depth write, so faces through the model will be stomped @@ -1472,7 +1492,18 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input, const VertexArrays // standard alpha surfs. stateBits |= GLS_DEPTHMASK_TRUE; } +#endif + } +#ifdef REND2_SP + if (backEnd.currentEntity->e.renderfx & RF_ALPHA_FADE) + { + if (backEnd.currentEntity->e.shaderRGBA[3] < 255) + { + stateBits = GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA; + forceAlphaGen = AGEN_ENTITY; + } } +#endif } if (backEnd.viewParms.flags & VPF_POINTSHADOW) @@ -1500,7 +1531,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input, const VertexArrays vec4_t baseColor; vec4_t vertColor; -#ifdef REND2_SP_MAYBE +#ifdef REND2_SP_GORE // Fade will be set true when rendering some gore surfaces if (input->fade) { @@ -1525,7 +1556,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input, const VertexArrays vertColor[3] = 0.0f; } - if (backEnd.currentEntity->e.hModel != NULL) + if (backEnd.currentEntity->e.hModel != NULL_HANDLE) { model_t *model = R_GetModelByHandle(backEnd.currentEntity->e.hModel); if (model->type != MOD_BRUSH) @@ -1580,9 +1611,9 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input, const VertexArrays uniformDataWriter.SetUniformVec3(UNIFORM_TONEMINAVGMAXLINEAR, tr.refdef.toneMinAvgMaxLinear); } -#ifdef REND2_SP_MAYBE +#ifdef REND2_SP_GORE // tess scale will be set true only when theres scaled gore - if (!input->scale) + if (input->scale) texMatrix[0] = texMatrix[3] = input->texCoords[input->firstIndex][0][0]; else #endif @@ -1591,8 +1622,19 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input, const VertexArrays uniformDataWriter.SetUniformVec4(UNIFORM_DIFFUSETEXMATRIX, texMatrix); uniformDataWriter.SetUniformVec4(UNIFORM_DIFFUSETEXOFFTURB, texOffTurb); - uniformDataWriter.SetUniformInt(UNIFORM_TCGEN0, pStage->bundle[0].tcGen); - uniformDataWriter.SetUniformInt(UNIFORM_TCGEN1, pStage->bundle[1].tcGen); + texCoordGen_t bundle0TcGen = pStage->bundle[0].tcGen; + texCoordGen_t bundle1TcGen = pStage->bundle[1].tcGen; +#ifdef REND2_SP + if (backEnd.currentEntity && backEnd.currentEntity->e.renderfx&RF_FIRST_PERSON) + { + if (bundle0TcGen == TCGEN_ENVIRONMENT_MAPPED_SP) + bundle0TcGen = TCGEN_ENVIRONMENT_MAPPED_SP_FP; + if (bundle1TcGen == TCGEN_ENVIRONMENT_MAPPED_SP) + bundle1TcGen = TCGEN_ENVIRONMENT_MAPPED_SP_FP; + } +#endif + uniformDataWriter.SetUniformInt(UNIFORM_TCGEN0, bundle0TcGen); + uniformDataWriter.SetUniformInt(UNIFORM_TCGEN1, bundle1TcGen); if (pStage->bundle[0].tcGen == TCGEN_VECTOR) { uniformDataWriter.SetUniformVec3(UNIFORM_TCGEN0VECTOR0, pStage->bundle[0].tcGenVectors[0]); @@ -1624,7 +1666,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input, const VertexArrays && input->cubemapIndex > 0 && pStage->rgbGen != CGEN_LIGHTMAPSTYLE ); bool enableDLights = ( tess.dlightBits - && tess.shader->sort <= SS_OPAQUE + && (pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK) && !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY)) && pStage->rgbGen != CGEN_LIGHTMAPSTYLE ); @@ -1649,11 +1691,29 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input, const VertexArrays samplerBindingsWriter.AddStaticImage(tr.whiteImage, 0); else if ( pStage->bundle[TB_COLORMAP].image[0] != 0 ) samplerBindingsWriter.AddAnimatedImage(&pStage->bundle[TB_COLORMAP], TB_COLORMAP); + + // TODO: remove light requirement + if (pStage->glslShaderIndex & LIGHTDEF_USE_PARALLAXMAP && + pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK) + { + vec4_t enableTextures = {}; + if (pStage->bundle[TB_NORMALMAP].image[0]) + { + samplerBindingsWriter.AddAnimatedImage(&pStage->bundle[TB_NORMALMAP], TB_NORMALMAP); + enableTextures[0] = 1.0f; + } + else if (r_normalMapping->integer) + { + samplerBindingsWriter.AddStaticImage(tr.whiteImage, TB_NORMALMAP); + } + uniformDataWriter.SetUniformVec4(UNIFORM_ENABLETEXTURES, enableTextures); + } } else if ( pStage->glslShaderGroup == tr.lightallShader ) { int i; vec4_t enableTextures = {}; + enableTextures[0] = (float)pStage->glow; if (r_sunlightMode->integer && (backEnd.viewParms.flags & VPF_USESUNLIGHT) && @@ -1713,7 +1773,6 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input, const VertexArrays if (pStage->bundle[TB_NORMALMAP].image[0]) { samplerBindingsWriter.AddAnimatedImage(&pStage->bundle[TB_NORMALMAP], TB_NORMALMAP); - enableTextures[0] = 1.0f; } else if (r_normalMapping->integer) { @@ -1758,6 +1817,10 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input, const VertexArrays { samplerBindingsWriter.AddAnimatedImage(&pStage->bundle[0], 0); samplerBindingsWriter.AddAnimatedImage(&pStage->bundle[1], 1); + + vec4_t enableTextures = {}; + enableTextures[0] = (float)pStage->glow; + uniformDataWriter.SetUniformVec4(UNIFORM_ENABLETEXTURES, enableTextures); } else { @@ -1765,6 +1828,9 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input, const VertexArrays // set state // samplerBindingsWriter.AddAnimatedImage(&pStage->bundle[0], 0); + vec4_t enableTextures = {}; + enableTextures[0] = (float)pStage->glow; + uniformDataWriter.SetUniformVec4(UNIFORM_ENABLETEXTURES, enableTextures); } // @@ -1992,7 +2058,7 @@ void RB_EndSurface( void ) { return; } - if (tr.world && !backEnd.framePostProcessed) { + if (tr.world && !backEnd.framePostProcessed && !(backEnd.refdef.rdflags & RDF_NOWORLDMODEL)) { if (tr.world->skyboxportal) { // world @@ -2029,6 +2095,10 @@ void RB_EndSurface( void ) { tess.firstIndex = 0; tess.multiDrawPrimitives = 0; tess.externalIBO = nullptr; +#ifdef REND2_SP_GORE + tess.fade = false; + tess.scale = false; +#endif glState.vertexAnimation = qfalse; glState.skeletalAnimation = qfalse; glState.genShadows = qfalse; diff --git a/codemp/rd-rend2/tr_shade_calc.cpp b/shared/rd-rend2/tr_shade_calc.cpp similarity index 97% rename from codemp/rd-rend2/tr_shade_calc.cpp rename to shared/rd-rend2/tr_shade_calc.cpp index d51a4e3b11..cca523af5d 100644 --- a/codemp/rd-rend2/tr_shade_calc.cpp +++ b/shared/rd-rend2/tr_shade_calc.cpp @@ -382,13 +382,8 @@ static void AutospriteDeform( void ) { tess.numIndexes = 0; tess.firstIndex = 0; - if ( backEnd.currentEntity != &tr.worldEntity ) { - GlobalVectorToLocal( backEnd.viewParms.ori.axis[1], leftDir ); - GlobalVectorToLocal( backEnd.viewParms.ori.axis[2], upDir ); - } else { - VectorCopy( backEnd.viewParms.ori.axis[1], leftDir ); - VectorCopy( backEnd.viewParms.ori.axis[2], upDir ); - } + VectorCopy( backEnd.viewParms.ori.axis[1], leftDir ); + VectorCopy( backEnd.viewParms.ori.axis[2], upDir ); for ( i = 0 ; i < oldVerts ; i+=4 ) { // find the midpoint @@ -455,11 +450,7 @@ static void Autosprite2Deform( void ) { ri.Printf( PRINT_WARNING, "Autosprite2 shader %s had odd index count\n", tess.shader->name ); } - if ( backEnd.currentEntity != &tr.worldEntity ) { - GlobalVectorToLocal( backEnd.viewParms.ori.axis[0], forward ); - } else { - VectorCopy( backEnd.viewParms.ori.axis[0], forward ); - } + VectorCopy( backEnd.viewParms.ori.axis[0], forward ); // this is a lot of work for two triangles... // we could precalculate a lot of it is an issue, but it would mess up diff --git a/codemp/rd-rend2/tr_shader.cpp b/shared/rd-rend2/tr_shader.cpp similarity index 97% rename from codemp/rd-rend2/tr_shader.cpp rename to shared/rd-rend2/tr_shader.cpp index f938dff0fc..ad793212eb 100644 --- a/codemp/rd-rend2/tr_shader.cpp +++ b/shared/rd-rend2/tr_shader.cpp @@ -32,8 +32,18 @@ static shader_t shader; static texModInfo_t texMods[MAX_SHADER_STAGES][TR_MAX_TEXMODS]; // Hash value (generated using the generateHashValueForText function) for the original -// retail JKA shader for gfx/2d/wedge. +// retail JK2/JKA shader for gfx/2d/wedge. +#ifdef JK2_MODE +#define RETAIL_ROCKET_WEDGE_SHADER_HASH (1193966) +#else #define RETAIL_ROCKET_WEDGE_SHADER_HASH (1217042) +#endif + +#ifndef JK2_MODE +// Hash value (generated using the generateHashValueForText function) for the original +// retail JKA shader for gfx/menus/radar/arrow_w. +#define RETAIL_ARROW_W_SHADER_HASH (1650186) +#endif #define FILE_HASH_SIZE 1024 static shader_t* hashTable[FILE_HASH_SIZE]; @@ -1495,7 +1505,11 @@ static qboolean ParseStage( shaderStage_t *stage, const char **text ) ri.Printf( PRINT_WARNING, "WARNING: missing parameter for 'videoMap' keyword in shader '%s'\n", shader.name ); return qfalse; } +#ifndef REND2_SP stage->bundle[0].videoMapHandle = ri.CIN_PlayCinematic( token, 0, 0, 256, 256, (CIN_loop | CIN_silent | CIN_shader)); +#else + stage->bundle[0].videoMapHandle = ri.CIN_PlayCinematic(token, 0, 0, 256, 256, (CIN_loop | CIN_silent | CIN_shader), NULL); +#endif if (stage->bundle[0].videoMapHandle != -1) { stage->bundle[0].isVideoMap = qtrue; stage->bundle[0].image[0] = tr.scratchImage[stage->bundle[0].videoMapHandle]; @@ -1950,7 +1964,11 @@ static qboolean ParseStage( shaderStage_t *stage, const char **text ) if ( !Q_stricmp( token, "environment" ) ) { +#ifndef REND2_SP stage->bundle[0].tcGen = TCGEN_ENVIRONMENT_MAPPED; +#else + stage->bundle[0].tcGen = TCGEN_ENVIRONMENT_MAPPED_SP; +#endif } else if ( !Q_stricmp( token, "lightmap" ) ) { @@ -2112,7 +2130,7 @@ static qboolean ParseStage( shaderStage_t *stage, const char **text ) { if (shader.isHDRLit) { - image_t *hdrImage = R_FindImageFile(bufferBaseColorTextureName, IMGTYPE_COLORALPHA, IMGFLAG_NOLIGHTSCALE | IMGFLAG_HDR_LIGHTMAP | IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE); + image_t *hdrImage = R_FindImageFile(bufferBaseColorTextureName, IMGTYPE_COLORALPHA, IMGFLAG_NOLIGHTSCALE | IMGFLAG_HDR | IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE); if (hdrImage) stage->bundle[0].image[0] = hdrImage; } @@ -2679,8 +2697,6 @@ static qboolean ParseShader( const char **text ) token = COM_ParseExt( text, qfalse ); tr.autoExposureMinMax[1] = atof( token ); - tr.explicitToneMap = true; - SkipRestOfLine( text ); continue; } @@ -2770,6 +2786,13 @@ static qboolean ParseShader( const char **text ) return qfalse; } + if (tr.hdrLighting) + { + shader.fogParms.color[0] = sRGBtoRGB(shader.fogParms.color[0]); + shader.fogParms.color[1] = sRGBtoRGB(shader.fogParms.color[1]); + shader.fogParms.color[2] = sRGBtoRGB(shader.fogParms.color[2]); + } + token = COM_ParseExt( text, qfalse ); if ( !token[0] ) { @@ -2863,6 +2886,23 @@ static qboolean ParseShader( const char **text ) stages[0].stateBits |= GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA; } +#ifndef JK2_MODE + // The basejka radar arrow contains an incorrect rgbGen of identity + // It only worked because the original code didn't check shaders at all, + // thus setcolor worked fine but with fixing RB_RotatePic it no longer + // functioned because rgbGen identity doesn't work with setcolor. + // + // We match against retail version of gfx/menus/radar/arrow_w by calculating + // the hash value of the shader text, and comparing it against a + // precalculated value. + if (shaderHash == RETAIL_ARROW_W_SHADER_HASH && + Q_stricmp(shader.name, "gfx/menus/radar/arrow_w") == 0) + { + stages[0].rgbGen = CGEN_VERTEX; + stages[0].alphaGen = AGEN_VERTEX; + } +#endif + return qtrue; } @@ -3007,6 +3047,8 @@ static void ComputeVertexAttribs(void) ATTR_TEXCOORD3 | ATTR_TEXCOORD4); break; case TCGEN_ENVIRONMENT_MAPPED: + case TCGEN_ENVIRONMENT_MAPPED_SP: + case TCGEN_ENVIRONMENT_MAPPED_SP_FP: shader.vertexAttribs |= ATTR_NORMAL; break; @@ -3193,14 +3235,14 @@ static void CollapseStagesToLightall(shaderStage_t *stage, shaderStage_t *lightm defs |= LIGHTDEF_USE_TCGEN_AND_TCMOD; } - if (stage->glow) - defs |= LIGHTDEF_USE_GLOW_BUFFER; + /*if (stage->glow) + defs |= LIGHTDEF_USE_GLOW_BUFFER;*/ if (stage->cloth) defs |= LIGHTDEF_USE_CLOTH_BRDF; - if (stage->alphaTestType != ALPHA_TEST_NONE) - defs |= LIGHTDEF_USE_ALPHA_TEST; + /*if (stage->alphaTestType != ALPHA_TEST_NONE) + defs |= LIGHTDEF_USE_ALPHA_TEST;*/ //ri.Printf(PRINT_ALL, ".\n"); @@ -3275,6 +3317,8 @@ static qboolean CollapseStagesToGLSL(void) case TCGEN_LIGHTMAP2: case TCGEN_LIGHTMAP3: case TCGEN_ENVIRONMENT_MAPPED: + case TCGEN_ENVIRONMENT_MAPPED_SP: + case TCGEN_ENVIRONMENT_MAPPED_SP_FP: case TCGEN_VECTOR: break; default: @@ -3328,11 +3372,20 @@ static qboolean CollapseStagesToGLSL(void) if (pStage->bundle[0].tcGen >= TCGEN_LIGHTMAP && pStage->bundle[0].tcGen <= TCGEN_LIGHTMAP3) continue; + if (i > 0) + { + int blendBits = pStage->stateBits & (GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS); + if (blendBits == (GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO) || + blendBits == (GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR)) + continue; + } + diffuse = pStage; parallax = qfalse; lightmap = NULL; + vertexlit = qfalse; - // we have a diffuse map, find matching lightmap + // we have a diffuse map, find matching lightmap or vertex lit stage for (j = i + 1; j < MAX_SHADER_STAGES; j++) { shaderStage_t *pStage2 = &stages[j]; @@ -3352,10 +3405,22 @@ static qboolean CollapseStagesToGLSL(void) lightmaps[j] = NULL; break; } + + if (pStage2->bundle[0].isLightmap && + pStage2->bundle[0].image[0] == tr.whiteImage && + pStage2->rgbGen == CGEN_EXACT_VERTEX) + { + int blendBits = pStage2->stateBits & (GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS); + if (blendBits == (GLS_DSTBLEND_SRC_COLOR | GLS_SRCBLEND_ZERO) || + blendBits == (GLS_DSTBLEND_ZERO | GLS_SRCBLEND_DST_COLOR)) + vertexlit = qtrue; + } } tcgen = qfalse; if (diffuse->bundle[0].tcGen == TCGEN_ENVIRONMENT_MAPPED + || diffuse->bundle[0].tcGen == TCGEN_ENVIRONMENT_MAPPED_SP + || diffuse->bundle[0].tcGen == TCGEN_ENVIRONMENT_MAPPED_SP_FP || (diffuse->bundle[0].tcGen >= TCGEN_LIGHTMAP && diffuse->bundle[0].tcGen <= TCGEN_LIGHTMAP3) || diffuse->bundle[0].tcGen == TCGEN_VECTOR) { @@ -3369,7 +3434,6 @@ static qboolean CollapseStagesToGLSL(void) diffuselit = qtrue; } - vertexlit = qfalse; if (diffuse->rgbGen == CGEN_VERTEX_LIT || diffuse->rgbGen == CGEN_EXACT_VERTEX_LIT || diffuse->rgbGen == CGEN_VERTEX || diffuse->rgbGen == CGEN_EXACT_VERTEX) { vertexlit = qtrue; @@ -3537,7 +3601,7 @@ static qboolean CollapseStagesToGLSL(void) return (qboolean)numStages; } - +#ifndef REND2_SP /* ============= @@ -3622,7 +3686,7 @@ static void FixRenderCommandList( int newShader ) { } } } - +#endif /* ============== SortNewShader @@ -3665,9 +3729,11 @@ static void SortNewShader( void ) { tr.sortedShaders[i+1]->sortedIndex++; } +#ifndef REND2_SP // Arnout: fix rendercommandlist // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=493 FixRenderCommandList( i+1 ); +#endif newShader->sortedIndex = i+1; tr.sortedShaders[i+1] = newShader; @@ -3689,7 +3755,7 @@ static shader_t *GeneratePermanentShader( void ) { return tr.defaultShader; } - newShader = (shader_t *)ri.Hunk_Alloc( sizeof( shader_t ), h_low ); + newShader = (shader_t *)Hunk_Alloc( sizeof( shader_t ), h_low ); *newShader = shader; @@ -3741,17 +3807,18 @@ static shader_t *GeneratePermanentShader( void ) { if ( !stages[i].active ) { break; } - newShader->stages[i] = (shaderStage_t *)ri.Hunk_Alloc( sizeof( stages[i] ), h_low ); + newShader->stages[i] = (shaderStage_t *)Hunk_Alloc( sizeof( stages[i] ), h_low ); *newShader->stages[i] = stages[i]; for ( b = 0 ; b < NUM_TEXTURE_BUNDLES ; b++ ) { size = newShader->stages[i]->bundle[b].numTexMods * sizeof( texModInfo_t ); - newShader->stages[i]->bundle[b].texMods = (texModInfo_t *)ri.Hunk_Alloc( size, h_low ); + newShader->stages[i]->bundle[b].texMods = (texModInfo_t *)Hunk_Alloc( size, h_low ); Com_Memcpy( newShader->stages[i]->bundle[b].texMods, stages[i].bundle[b].texMods, size ); } } RB_AddShaderToShaderInstanceUBO(newShader); + newShader->spriteUbo = 0; SortNewShader(); @@ -4149,6 +4216,13 @@ static shader_t *FinishShader( void ) { hasLightmapStage = qfalse; } + // Handle special glow case + if (stage == 1 && stages[0].glow && shader.sort < SS_OPAQUE) + { + shader.sort = SS_BLEND1; + stages[0].stateBits |= GLS_COLORMASK_BUF1; + } + // // look for multitexture potential // @@ -4179,6 +4253,9 @@ static shader_t *FinishShader( void ) { if (!pStage->active) continue; + if (pStage->stateBits & (GLS_DSTBLEND_BITS | GLS_SRCBLEND_BITS)) + break; + if (pStage->alphaTestType == ALPHA_TEST_NONE) shader.useSimpleDepthShader = qtrue; break; @@ -4432,6 +4509,9 @@ shader_t *R_FindShader( const char *name, const int *lightmapIndexes, const byte // // attempt to define shader from an explicit parameter file // +#ifdef REND2_SP + COM_BeginParseSession(); +#endif shaderText = FindShaderInShaderText( strippedName ); if ( shaderText ) { // enable this when building a pak file to get a global list @@ -4445,8 +4525,14 @@ shader_t *R_FindShader( const char *name, const int *lightmapIndexes, const byte shader.defaultShader = qtrue; } sh = FinishShader(); +#ifdef REND2_SP + COM_EndParseSession(); +#endif return sh; } +#ifdef REND2_SP + COM_EndParseSession(); +#endif // @@ -4907,7 +4993,11 @@ static void ScanAndLoadShaderFiles( void ) // Do a simple check on the shader structure in that file to make sure one bad shader file cannot fuck up all other shaders. p = buffers[i]; +#ifndef REND2_SP COM_BeginParseSession(filename); +#else + COM_BeginParseSession(); +#endif while(1) { token = COM_ParseExt(&p, qtrue); @@ -4953,11 +5043,15 @@ static void ScanAndLoadShaderFiles( void ) if (buffers[i]) - sum += summand; + sum += summand; + +#ifdef REND2_SP + COM_EndParseSession(); +#endif } // build single large buffer - s_shaderText = (char *)ri.Hunk_Alloc( sum + numShaderFiles*2, h_low ); + s_shaderText = (char *)Hunk_Alloc( sum + numShaderFiles*2, h_low ); s_shaderText[ 0 ] = '\0'; textEnd = s_shaderText; @@ -4981,6 +5075,10 @@ static void ScanAndLoadShaderFiles( void ) Com_Memset(shaderTextHashTableSizes, 0, sizeof(shaderTextHashTableSizes)); size = 0; +#ifdef REND2_SP + COM_BeginParseSession(); +#endif + p = s_shaderText; // look for shader names while ( 1 ) { @@ -4997,7 +5095,7 @@ static void ScanAndLoadShaderFiles( void ) size += MAX_SHADERTEXT_HASH; - hashMem = (char *)ri.Hunk_Alloc( size * sizeof(char *), h_low ); + hashMem = (char *)Hunk_Alloc( size * sizeof(char *), h_low ); for (i = 0; i < MAX_SHADERTEXT_HASH; i++) { shaderTextHashTable[i] = (char **) hashMem; @@ -5021,6 +5119,10 @@ static void ScanAndLoadShaderFiles( void ) SkipBracedSection(&p, 0); } +#ifdef REND2_SP + COM_EndParseSession(); +#endif + return; } diff --git a/codemp/rd-rend2/tr_shadows.cpp b/shared/rd-rend2/tr_shadows.cpp similarity index 95% rename from codemp/rd-rend2/tr_shadows.cpp rename to shared/rd-rend2/tr_shadows.cpp index eb0b472dfc..50a1475272 100644 --- a/codemp/rd-rend2/tr_shadows.cpp +++ b/shared/rd-rend2/tr_shadows.cpp @@ -39,15 +39,12 @@ void RB_ShadowFinish(void) { return; } - GL_Cull(CT_TWO_SIDED); - GL_BindToTMU(tr.whiteImage, TB_COLORMAP); GL_State(GLS_STENCILTEST_ENABLE | GLS_DEPTHMASK_TRUE | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO); qglStencilFunc(GL_NOTEQUAL, 0, 0xff); - qglViewport(0, 0, glConfig.vidWidth, glConfig.vidHeight); - qglScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight); + GL_SetViewportAndScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight); matrix_t projection; Matrix16Ortho(0, glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1, projection); diff --git a/codemp/rd-rend2/tr_skin.cpp b/shared/rd-rend2/tr_skin.cpp similarity index 82% rename from codemp/rd-rend2/tr_skin.cpp rename to shared/rd-rend2/tr_skin.cpp index 69c9c9d204..b5ba142159 100644 --- a/codemp/rd-rend2/tr_skin.cpp +++ b/shared/rd-rend2/tr_skin.cpp @@ -1,5 +1,8 @@ #include "tr_local.h" +#ifdef REND2_SP +#include "../qcommon/sstring.h" +#endif /* ============================================================================ @@ -125,6 +128,7 @@ qhandle_t RE_RegisterIndividualSkin( const char *name , qhandle_t hSkin) // parse the shader name token = CommaParse( &text_p ); +#ifndef JK2_MODE if ( !strcmp( &surfName[strlen(surfName)-4], "_off") ) { if ( !strcmp( token ,"*off" ) ) @@ -133,6 +137,7 @@ qhandle_t RE_RegisterIndividualSkin( const char *name , qhandle_t hSkin) } surfName[strlen(surfName)-4] = 0; //remove the "_off" } +#endif if ( (unsigned)skin->numSurfaces >= ARRAY_LEN( skin->surfaces ) ) { assert( ARRAY_LEN( skin->surfaces ) > (unsigned)skin->numSurfaces ); @@ -140,7 +145,7 @@ qhandle_t RE_RegisterIndividualSkin( const char *name , qhandle_t hSkin) break; } surf = (skinSurface_t *) Hunk_Alloc( sizeof( *skin->surfaces[0] ), h_low ); - skin->surfaces[skin->numSurfaces] = (_skinSurface_t *)surf; + skin->surfaces[skin->numSurfaces] = (skinSurface_t *)surf; Q_strncpyz( surf->name, surfName, sizeof( surf->name ) ); @@ -191,23 +196,23 @@ qhandle_t RE_RegisterSkin( const char *name ) { return 0; } tr.numSkins++; - skin = (struct skin_s *)Hunk_Alloc( sizeof( skin_t ), h_low ); + skin = (skin_s *)Hunk_Alloc( sizeof( skin_t ), h_low ); tr.skins[hSkin] = skin; Q_strncpyz( skin->name, name, sizeof( skin->name ) ); skin->numSurfaces = 0; // make sure the render thread is stopped R_IssuePendingRenderCommands(); - +#ifdef JK2_MODE // If not a .skin file, load as a single shader if ( strcmp( name + strlen( name ) - 5, ".skin" ) ) { -/* skin->numSurfaces = 1; + skin->numSurfaces = 1; skin->surfaces[0] = (skinSurface_t *)Hunk_Alloc( sizeof(skin->surfaces[0]), h_low ); skin->surfaces[0]->shader = R_FindShader( name, lightmapsNone, stylesDefault, qtrue ); return hSkin; -*/ - } + } +#endif char skinhead[MAX_QPATH]={0}; char skintorso[MAX_QPATH]={0}; char skinlower[MAX_QPATH]={0}; @@ -339,6 +344,7 @@ static char *CommaParse( char **data_p ) { return com_token; } +#ifndef REND2_SP /* =============== RE_RegisterServerSkin @@ -362,6 +368,66 @@ qhandle_t RE_RegisterServerSkin( const char *name ) { return r; } +#else +/* +class CStringComparator +{ +public: + bool operator()(const char *s1, const char *s2) const { return(stricmp(s1, s2) < 0); } +}; +*/ +typedef std::map AnimationCFGs_t; +AnimationCFGs_t AnimationCFGs; + +// I added this function for development purposes (and it's VM-safe) so we don't have problems +// with our use of cached models but uncached animation.cfg files (so frame sequences are out of sync +// if someone rebuild the model while you're ingame and you change levels)... +// +// Usage: call with psDest == NULL for a size enquire (for malloc), +// then with NZ ptr for it to copy to your supplied buffer... +// +int RE_GetAnimationCFG(const char *psCFGFilename, char *psDest, int iDestSize) +{ + char *psText = NULL; + + AnimationCFGs_t::iterator it = AnimationCFGs.find(psCFGFilename); + if (it != AnimationCFGs.end()) + { + psText = (*it).second; + } + else + { + // not found, so load it... + // + fileHandle_t f; + int iLen = ri.FS_FOpenFileRead(psCFGFilename, &f, qfalse); + if (iLen <= 0) + { + return 0; + } + + psText = (char *)R_Malloc(iLen + 1, TAG_ANIMATION_CFG, qfalse); + + ri.FS_Read(psText, iLen, f); + psText[iLen] = '\0'; + ri.FS_FCloseFile(f); + + AnimationCFGs[psCFGFilename] = psText; + } + + if (psText) // sanity, but should always be NZ + { + if (psDest) + { + Q_strncpyz(psDest, psText, iDestSize); + } + + return strlen(psText); + } + + return 0; +} +#endif /* =============== @@ -374,10 +440,10 @@ void R_InitSkins( void ) { tr.numSkins = 1; // make the default skin have all default shaders - skin = tr.skins[0] = (struct skin_s *)ri.Hunk_Alloc( sizeof( skin_t ), h_low ); + skin = tr.skins[0] = (struct skin_s *)Hunk_Alloc( sizeof( skin_t ), h_low ); Q_strncpyz( skin->name, "", sizeof( skin->name ) ); skin->numSurfaces = 1; - skin->surfaces[0] = (_skinSurface_t *)ri.Hunk_Alloc( sizeof( skinSurface_t ), h_low ); + skin->surfaces[0] = (skinSurface_t *)Hunk_Alloc( sizeof( skinSurface_t ), h_low ); skin->surfaces[0]->shader = tr.defaultShader; } diff --git a/codemp/rd-rend2/tr_sky.cpp b/shared/rd-rend2/tr_sky.cpp similarity index 98% rename from codemp/rd-rend2/tr_sky.cpp rename to shared/rd-rend2/tr_sky.cpp index 9f9d8eb148..26f80c08a5 100644 --- a/codemp/rd-rend2/tr_sky.cpp +++ b/shared/rd-rend2/tr_sky.cpp @@ -451,10 +451,13 @@ static void DrawSkySide( struct image_s *image, const int mins[2], const int max UNIFORM_DIFFUSETEXMATRIX, 1.0f, 0.0f, 0.0f, 1.0f); uniformDataWriter.SetUniformVec4( UNIFORM_DIFFUSETEXOFFTURB, 0.0f, 0.0f, 0.0f, 0.0f); + uniformDataWriter.SetUniformVec4( + UNIFORM_ENABLETEXTURES, 0.0f, 0.0f, 0.0f, 0.0f); samplerBindingsWriter.AddStaticImage(image, TB_DIFFUSEMAP); - const GLuint currentFrameUbo = backEndData->currentFrame->ubo; + const byte currentFrameScene = backEndData->currentFrame->currentScene; + const GLuint currentFrameUbo = backEndData->currentFrame->ubo[currentFrameScene]; const UniformBlockBinding uniformBlockBindings[] = { { currentFrameUbo, tr.skyEntityUboOffset, UNIFORM_BLOCK_ENTITY }, { currentFrameUbo, tr.cameraUboOffsets[tr.viewParms.currentViewParm], UNIFORM_BLOCK_CAMERA } diff --git a/codemp/rd-rend2/tr_subs.cpp b/shared/rd-rend2/tr_subs.cpp similarity index 62% rename from codemp/rd-rend2/tr_subs.cpp rename to shared/rd-rend2/tr_subs.cpp index 0228319861..8e01c88f24 100644 --- a/codemp/rd-rend2/tr_subs.cpp +++ b/shared/rd-rend2/tr_subs.cpp @@ -44,8 +44,11 @@ void QDECL Com_OPrintf( const char *msg, ... ) va_start(argptr, msg); Q_vsnprintf(text, sizeof(text), msg, argptr); va_end(argptr); - +#ifndef REND2_SP ri.OPrintf("%s", text); +#else + ri.Printf(PRINT_ALL, "%s", text); +#endif } void QDECL Com_Error( int level, const char *error, ... ) @@ -60,31 +63,42 @@ void QDECL Com_Error( int level, const char *error, ... ) ri.Error(level, "%s", text); } -// HUNK -void *Hunk_AllocateTempMemory( int size ) { - return ri.Hunk_AllocateTempMemory( size ); + + +// ZONE +void *Z_Malloc( int iSize, memtag_t eTag, qboolean bZeroit, int iAlign ) { + return ri.Z_Malloc( iSize, eTag, bZeroit, iAlign ); } -void Hunk_FreeTempMemory( void *buf ) { - ri.Hunk_FreeTempMemory( buf ); +void* R_Malloc(int iSize, memtag_t eTag) +{ + return ri.Z_Malloc(iSize, eTag, qtrue, 4); } -void *Hunk_Alloc( int size, ha_pref preference ) { - return ri.Hunk_Alloc( size, preference ); +void* R_Malloc(int iSize, memtag_t eTag, qboolean bZeroit) +{ + return ri.Z_Malloc(iSize, eTag, bZeroit, 4); } -int Hunk_MemoryRemaining( void ) { - return ri.Hunk_MemoryRemaining(); +#ifdef REND2_SP +void* R_Malloc(int iSize, memtag_t eTag, qboolean bZeroit, int iAlign) +{ + return ri.Z_Malloc(iSize, eTag, bZeroit, iAlign); } -// ZONE -void *Z_Malloc( int iSize, memtag_t eTag, qboolean bZeroit, int iAlign ) { - return ri.Z_Malloc( iSize, eTag, bZeroit, iAlign ); +int Z_Free( void *ptr ) { + return ri.Z_Free( ptr ); } -void Z_Free( void *ptr ) { - ri.Z_Free( ptr ); +void R_Free(void *ptr) +{ + ri.Z_Free(ptr); +} +#else +void Z_Free(void *ptr) { + ri.Z_Free(ptr); } +#endif int Z_MemSize( memtag_t eTag ) { return ri.Z_MemSize( eTag ); @@ -93,3 +107,42 @@ int Z_MemSize( memtag_t eTag ) { void Z_MorphMallocTag( void *pvBuffer, memtag_t eDesiredTag ) { ri.Z_MorphMallocTag( pvBuffer, eDesiredTag ); } + +// HUNK +#ifdef REND2_SP +//void* Hunk_Alloc(int iSize, ha_pref preferences) +//{ +// return Hunk_Alloc(iSize, qtrue); +//} + +void* Hunk_Alloc(int size, ha_pref preference) { + return R_Malloc(size, TAG_HUNKALLOC, qtrue); +} + +void* Hunk_AllocateTempMemory(int size) { + // don't bother clearing, because we are going to load a file over it + return R_Malloc(size, TAG_TEMP_HUNKALLOC, qfalse); +} + +void Hunk_FreeTempMemory(void* buf) +{ + ri.Z_Free(buf); +} +#else + +void *Hunk_AllocateTempMemory(int size) { + return ri.Hunk_AllocateTempMemory(size); +} + +void Hunk_FreeTempMemory(void *buf) { + ri.Hunk_FreeTempMemory(buf); +} + +void *Hunk_Alloc(int size, ha_pref preference) { + return ri.Hunk_Alloc(size, preference); +} + +int Hunk_MemoryRemaining(void) { + return ri.Hunk_MemoryRemaining(); +} +#endif \ No newline at end of file diff --git a/codemp/rd-rend2/tr_surface.cpp b/shared/rd-rend2/tr_surface.cpp similarity index 83% rename from codemp/rd-rend2/tr_surface.cpp rename to shared/rd-rend2/tr_surface.cpp index 95bb89c24e..a8ab779abd 100644 --- a/codemp/rd-rend2/tr_surface.cpp +++ b/shared/rd-rend2/tr_surface.cpp @@ -818,7 +818,7 @@ static void DoLine( const vec3_t start, const vec3_t end, const vec3_t up, float tess.indexes[tess.numIndexes++] = vbase + 3; } -static void DoLine2( const vec3_t start, const vec3_t end, const vec3_t up, float spanWidth, float spanWidth2 ) +static void DoLine2(const vec3_t start, const vec3_t end, const vec3_t up, float spanWidth, float spanWidth2, const float tcStart = 0.0f, const float tcEnd = 1.0f) { int vbase; @@ -828,26 +828,26 @@ static void DoLine2( const vec3_t start, const vec3_t end, const vec3_t up, floa VectorMA( start, spanWidth, up, tess.xyz[tess.numVertexes] ); tess.texCoords[tess.numVertexes][0][0] = 0; - tess.texCoords[tess.numVertexes][0][1] = 0; + tess.texCoords[tess.numVertexes][0][1] = tcStart; VectorScale4 (backEnd.currentEntity->e.shaderRGBA, 1.0f / 255.0f, tess.vertexColors[tess.numVertexes]); tess.numVertexes++; VectorMA( start, -spanWidth, up, tess.xyz[tess.numVertexes] ); tess.texCoords[tess.numVertexes][0][0] = 1;//backEnd.currentEntity->e.shaderTexCoord[0]; - tess.texCoords[tess.numVertexes][0][1] = 0; + tess.texCoords[tess.numVertexes][0][1] = tcStart; VectorScale4 (backEnd.currentEntity->e.shaderRGBA, 1.0f / 255.0f, tess.vertexColors[tess.numVertexes]); tess.numVertexes++; VectorMA( end, spanWidth2, up, tess.xyz[tess.numVertexes] ); tess.texCoords[tess.numVertexes][0][0] = 0; - tess.texCoords[tess.numVertexes][0][1] = 1;//backEnd.currentEntity->e.shaderTexCoord[1]; + tess.texCoords[tess.numVertexes][0][1] = tcEnd;//backEnd.currentEntity->e.shaderTexCoord[1]; VectorScale4 (backEnd.currentEntity->e.shaderRGBA, 1.0f / 255.0f, tess.vertexColors[tess.numVertexes]); tess.numVertexes++; VectorMA( end, -spanWidth2, up, tess.xyz[tess.numVertexes] ); tess.texCoords[tess.numVertexes][0][0] = 1;//backEnd.currentEntity->e.shaderTexCoord[0]; - tess.texCoords[tess.numVertexes][0][1] = 1;//backEnd.currentEntity->e.shaderTexCoord[1]; + tess.texCoords[tess.numVertexes][0][1] = tcEnd;//backEnd.currentEntity->e.shaderTexCoord[1]; VectorScale4 (backEnd.currentEntity->e.shaderRGBA, 1.0f / 255.0f, tess.vertexColors[tess.numVertexes]); tess.numVertexes++; @@ -904,35 +904,32 @@ static void DoLine_Oriented( const vec3_t start, const vec3_t end, const vec3_t tess.indexes[tess.numIndexes++] = vbase + 3; } -//----------------- -// RB_SurfaceLine -//----------------- -static void RB_SurfaceLine( void ) +static void RB_SurfaceOrientedLine(void) { refEntity_t *e; vec3_t right; vec3_t start, end; - vec3_t v1, v2; e = &backEnd.currentEntity->e; - VectorCopy( e->oldorigin, end ); - VectorCopy( e->origin, start ); + VectorCopy(e->oldorigin, end); + VectorCopy(e->origin, start); // compute side vector - VectorSubtract( start, backEnd.viewParms.ori.origin, v1 ); - VectorSubtract( end, backEnd.viewParms.ori.origin, v2 ); - CrossProduct( v1, v2, right ); - VectorNormalize( right ); - - DoLine( start, end, right, e->radius); + VectorNormalize(e->axis[1]); + VectorCopy(e->axis[1], right); + DoLine_Oriented(start, end, right, e->data.line.width*0.5); } -static void RB_SurfaceOrientedLine( void ) +//----------------- +// RB_SurfaceLine +//----------------- +static void RB_SurfaceLine( void ) { refEntity_t *e; vec3_t right; vec3_t start, end; + vec3_t v1, v2; e = &backEnd.currentEntity->e; @@ -940,9 +937,12 @@ static void RB_SurfaceOrientedLine( void ) VectorCopy( e->origin, start ); // compute side vector - VectorNormalize( e->axis[1] ); - VectorCopy(e->axis[1], right); - DoLine_Oriented( start, end, right, e->data.line.width*0.5 ); + VectorSubtract( start, backEnd.viewParms.ori.origin, v1 ); + VectorSubtract( end, backEnd.viewParms.ori.origin, v2 ); + CrossProduct( v1, v2, right ); + VectorNormalize( right ); + + DoLine( start, end, right, e->radius); } /* @@ -1112,6 +1112,7 @@ static float Q_crandom( int *seed ) { static void CreateShape() //---------------------------------------------------------------------------- { +#ifndef REND2_SP VectorSet( sh1, 0.66f + Q_flrand(-1.0f, 1.0f) * 0.1f, // fwd 0.07f + Q_flrand(-1.0f, 1.0f) * 0.025f, 0.07f + Q_flrand(-1.0f, 1.0f) * 0.025f ); @@ -1120,10 +1121,20 @@ static void CreateShape() VectorSet( sh2, 0.33f + Q_flrand(-1.0f, 1.0f) * 0.1f, // fwd -sh1[1] + Q_flrand(-1.0f, 1.0f) * 0.02f, // forcing point to be on the opposite side of the line -- right -sh1[2] + Q_flrand(-1.0f, 1.0f) * 0.02f );// up +#else + VectorSet(sh1, 0.66f,// + Q_flrand(-1.0f, 1.0f) * 0.1f, // fwd + 0.08f + Q_flrand(-1.0f, 1.0f) * 0.02f, + 0.08f + Q_flrand(-1.0f, 1.0f) * 0.02f); + + // it seems to look best to have a point on one side of the ideal line, then the other point on the other side. + VectorSet(sh2, 0.33f,// + Q_flrand(-1.0f, 1.0f) * 0.1f, // fwd + -sh1[1] + Q_flrand(-1.0f, 1.0f) * 0.02f, // forcing point to be on the opposite side of the line -- right + -sh1[2] + Q_flrand(-1.0f, 1.0f) * 0.02f);// up +#endif } //---------------------------------------------------------------------------- -static void ApplyShape( vec3_t start, vec3_t end, vec3_t right, float sradius, float eradius, int count ) +static void ApplyShape( vec3_t start, vec3_t end, vec3_t right, float sradius, float eradius, int count, float startPerc = 0.0f, float endPerc = 1.0f) //---------------------------------------------------------------------------- { vec3_t point1, point2, fwd; @@ -1133,7 +1144,7 @@ static void ApplyShape( vec3_t start, vec3_t end, vec3_t right, float sradius, f if ( count < 1 ) { // done recursing - DoLine2( start, end, right, sradius, eradius ); + DoLine2( start, end, right, sradius, eradius, startPerc, endPerc); return; } @@ -1157,7 +1168,11 @@ static void ApplyShape( vec3_t start, vec3_t end, vec3_t right, float sradius, f rads2 = sradius * 0.333f + eradius * 0.666f; // recursion +#ifndef REND2_SP ApplyShape( start, point1, right, sradius, rads1, count - 1 ); +#else + ApplyShape( start, point1, right, sradius, rads1, count - 1, startPerc, startPerc * 0.666f + endPerc * 0.333f); +#endif perc = sh2[0]; @@ -1167,8 +1182,13 @@ static void ApplyShape( vec3_t start, vec3_t end, vec3_t right, float sradius, f VectorMA( point2, dis * sh2[2], up, point2 ); // recursion +#ifndef REND2_SP ApplyShape( point2, point1, right, rads1, rads2, count - 1 ); ApplyShape( point2, end, right, rads2, eradius, count - 1 ); +#else + ApplyShape(point2, point1, right, rads1, rads2, count - 1, startPerc * 0.333f + endPerc * 0.666f, startPerc * 0.666f + endPerc * 0.333f); + ApplyShape(point2, end, right, rads2, eradius, count - 1, startPerc * 0.333f + endPerc * 0.666f, endPerc); +#endif } //---------------------------------------------------------------------------- @@ -1188,16 +1208,31 @@ static void DoBoltSeg( vec3_t start, vec3_t end, vec3_t right, float radius ) VectorSubtract( end, start, fwd ); dis = VectorNormalize( fwd ); +#ifdef REND2_SP + if (dis > 2000) //freaky long + { + // ri.Printf( PRINT_WARNING, "DoBoltSeg: insane distance.\n" ); + dis = 2000; + } +#endif + MakeNormalVectors( fwd, rt, up ); VectorCopy( start, old ); - + +#ifndef REND2_SP oldRadius = newRadius = radius; - - for ( i = 20; i <= dis; i+= 20 ) + for (i = 20; i <= dis; i += 20) + { + // because of our large step size, we may not actually draw to the end. In this case, fudge our percent so that we are basically complete + if (i + 20 > dis) +#else + newRadius = oldRadius = radius; + for (i = 16; i <= dis; i += 16) { // because of our large step size, we may not actually draw to the end. In this case, fudge our percent so that we are basically complete - if ( i + 20 > dis ) + if (i + 16 > dis) +#endif { perc = 1.0f; } @@ -1209,8 +1244,13 @@ static void DoBoltSeg( vec3_t start, vec3_t end, vec3_t right, float radius ) // create our level of deviation for this point VectorScale( fwd, Q_crandom(&e->frame) * 3.0f, temp ); // move less in fwd direction, chaos also does not affect this +#ifndef REND2_SP VectorMA( temp, Q_crandom(&e->frame) * 7.0f * e->axis[0][0], rt, temp ); // move more in direction perpendicular to line, angles is really the chaos VectorMA( temp, Q_crandom(&e->frame) * 7.0f * e->axis[0][0], up, temp ); // move more in direction perpendicular to line +#else + VectorMA(temp, Q_crandom(&e->frame) * 7.0f * e->angles[0], rt, temp); // move more in direction perpendicular to line, angles is really the chaos + VectorMA(temp, Q_crandom(&e->frame) * 7.0f * e->angles[0], up, temp); // move more in direction perpendicular to line +#endif // track our total level of offset from the ideal line VectorAdd( off, temp, off ); @@ -1230,7 +1270,11 @@ static void DoBoltSeg( vec3_t start, vec3_t end, vec3_t right, float radius ) } // Apply the random shape to our line seg to give it some micro-detail-jaggy-coolness. +#ifndef REND2_SP ApplyShape( cur, old, right, newRadius, oldRadius, LIGHTNING_RECURSION_LEVEL ); +#else + ApplyShape(cur, old, right, newRadius, oldRadius, 2 - r_lodbias->integer, 0, 1); +#endif // randomly split off to create little tendrils, but don't do it too close to the end and especially if we are not even of the forked variety if ( ( e->renderfx & RF_FORKED ) && f_count > 0 && Q_random(&e->frame) > 0.94f && radius * (1.0f - perc) > 0.2f ) @@ -1280,8 +1324,11 @@ static void RB_SurfaceElectricity() // see if we should grow from start to end if ( e->renderfx & RF_GROW ) { +#ifndef REND2_SP perc = 1.0f - ( e->axis[0][2]/*endTime*/ - tr.refdef.time ) / e->axis[0][1]/*duration*/; - +#else + perc = 1.0f - (e->endTime - tr.refdef.time) / e->angles[1]/*duration*/; +#endif if ( perc > 1.0f ) { perc = 1.0f; @@ -1300,7 +1347,9 @@ static void RB_SurfaceElectricity() VectorSubtract( end, backEnd.viewParms.ori.origin, v2 ); CrossProduct( v1, v2, right ); VectorNormalize( right ); - +#ifdef REND2_SP + f_count = 3; +#endif DoBoltSeg( start, end, right, radius ); } @@ -1959,6 +2008,331 @@ static void RB_SurfaceBSPGrid( srfBspSurface_t *srf ) { } } +#define LATHE_SEG_STEP 10 +#define BEZIER_STEP 0.05f // must be in the range of 0 to 1 + +// FIXME: This function is horribly expensive +static void RB_SurfaceLathe() +{ + refEntity_t *e; + vec2_t pt, oldpt, l_oldpt; + vec2_t pt2, oldpt2, l_oldpt2; + float bezierStep, latheStep; + float temp, mu, mum1; + float mum13, mu3, group1, group2; + float s, c, d = 1.0f, pain = 0.0f; + int i, t, vbase; + + e = &backEnd.currentEntity->e; + + if (e->endTime && e->endTime > backEnd.refdef.time) + { + d = 1.0f - (e->endTime - backEnd.refdef.time) / 1000.0f; + } + + if (e->frame && e->frame + 1000 > backEnd.refdef.time) + { + pain = (backEnd.refdef.time - e->frame) / 1000.0f; + // pain *= pain; + pain = (1.0f - pain) * 0.08f; + } + + VectorSet2(l_oldpt, e->axis[0][0], e->axis[0][1]); + + // do scalability stuff...r_lodbias 0-3 + int lod = r_lodbias->integer + 1; + if (lod > 4) + { + lod = 4; + } + if (lod < 1) + { + lod = 1; + } + bezierStep = BEZIER_STEP * lod; + latheStep = LATHE_SEG_STEP * lod; + + // Do bezier profile strip, then lathe this around to make a 3d model + for (mu = 0.0f; mu <= 1.01f * d; mu += bezierStep) + { + // Four point curve + mum1 = 1 - mu; + mum13 = mum1 * mum1 * mum1; + mu3 = mu * mu * mu; + group1 = 3 * mu * mum1 * mum1; + group2 = 3 * mu * mu *mum1; + + // Calc the current point on the curve + for (i = 0; i < 2; i++) + { + l_oldpt2[i] = mum13 * e->axis[0][i] + group1 * e->axis[1][i] + group2 * e->axis[2][i] + mu3 * e->oldorigin[i]; + } + + VectorSet2(oldpt, l_oldpt[0], 0); + VectorSet2(oldpt2, l_oldpt2[0], 0); + + // lathe patch section around in a complete circle + for (t = latheStep; t <= 360; t += latheStep) + { + VectorSet2(pt, l_oldpt[0], 0); + VectorSet2(pt2, l_oldpt2[0], 0); + + s = sin(DEG2RAD(t)); + c = cos(DEG2RAD(t)); + + // rotate lathe points +//c -s 0 +//s c 0 +//0 0 1 + temp = c * pt[0] - s * pt[1]; + pt[1] = s * pt[0] + c * pt[1]; + pt[0] = temp; + temp = c * pt2[0] - s * pt2[1]; + pt2[1] = s * pt2[0] + c * pt2[1]; + pt2[0] = temp; + + RB_CHECKOVERFLOW(4, 6); + + vbase = tess.numVertexes; + + vec3_t normal; + + // Actually generate the necessary verts + VectorSet(normal, oldpt[0], oldpt[1], l_oldpt[1]); + VectorAdd(e->origin, normal, tess.xyz[tess.numVertexes]); + VectorNormalize(normal); + tess.normal[tess.numVertexes] = R_VboPackNormal(normal); + i = oldpt[0] * 0.1f + oldpt[1] * 0.1f; + tess.texCoords[tess.numVertexes][0][0] = (t - latheStep) / 360.0f; + tess.texCoords[tess.numVertexes][0][1] = mu - bezierStep + cos(i + backEnd.refdef.floatTime) * pain; + tess.vertexColors[tess.numVertexes][0] = e->shaderRGBA[0]; + tess.vertexColors[tess.numVertexes][1] = e->shaderRGBA[1]; + tess.vertexColors[tess.numVertexes][2] = e->shaderRGBA[2]; + tess.vertexColors[tess.numVertexes][3] = e->shaderRGBA[3]; + tess.numVertexes++; + + VectorSet(normal, oldpt2[0], oldpt2[1], l_oldpt2[1]); + VectorAdd(e->origin, normal, tess.xyz[tess.numVertexes]); + VectorNormalize(normal); + tess.normal[tess.numVertexes] = R_VboPackNormal(normal); + i = oldpt2[0] * 0.1f + oldpt2[1] * 0.1f; + tess.texCoords[tess.numVertexes][0][0] = (t - latheStep) / 360.0f; + tess.texCoords[tess.numVertexes][0][1] = mu + cos(i + backEnd.refdef.floatTime) * pain; + tess.vertexColors[tess.numVertexes][0] = e->shaderRGBA[0]; + tess.vertexColors[tess.numVertexes][1] = e->shaderRGBA[1]; + tess.vertexColors[tess.numVertexes][2] = e->shaderRGBA[2]; + tess.vertexColors[tess.numVertexes][3] = e->shaderRGBA[3]; + tess.numVertexes++; + + VectorSet(normal, pt[0], pt[1], l_oldpt[1]); + VectorAdd(e->origin, normal, tess.xyz[tess.numVertexes]); + VectorNormalize(normal); + tess.normal[tess.numVertexes] = R_VboPackNormal(normal); + i = pt[0] * 0.1f + pt[1] * 0.1f; + tess.texCoords[tess.numVertexes][0][0] = t / 360.0f; + tess.texCoords[tess.numVertexes][0][1] = mu - bezierStep + cos(i + backEnd.refdef.floatTime) * pain; + tess.vertexColors[tess.numVertexes][0] = e->shaderRGBA[0]; + tess.vertexColors[tess.numVertexes][1] = e->shaderRGBA[1]; + tess.vertexColors[tess.numVertexes][2] = e->shaderRGBA[2]; + tess.vertexColors[tess.numVertexes][3] = e->shaderRGBA[3]; + tess.numVertexes++; + + VectorSet(normal, pt2[0], pt2[1], l_oldpt2[1]); + VectorAdd(e->origin, normal, tess.xyz[tess.numVertexes]); + VectorNormalize(normal); + tess.normal[tess.numVertexes] = R_VboPackNormal(normal); + i = pt2[0] * 0.1f + pt2[1] * 0.1f; + tess.texCoords[tess.numVertexes][0][0] = t / 360.0f; + tess.texCoords[tess.numVertexes][0][1] = mu + cos(i + backEnd.refdef.floatTime) * pain; + tess.vertexColors[tess.numVertexes][0] = e->shaderRGBA[0]; + tess.vertexColors[tess.numVertexes][1] = e->shaderRGBA[1]; + tess.vertexColors[tess.numVertexes][2] = e->shaderRGBA[2]; + tess.vertexColors[tess.numVertexes][3] = e->shaderRGBA[3]; + tess.numVertexes++; + + tess.indexes[tess.numIndexes++] = vbase; + tess.indexes[tess.numIndexes++] = vbase + 1; + tess.indexes[tess.numIndexes++] = vbase + 3; + + tess.indexes[tess.numIndexes++] = vbase + 3; + tess.indexes[tess.numIndexes++] = vbase + 2; + tess.indexes[tess.numIndexes++] = vbase; + + // Shuffle new points to old + VectorCopy2(pt, oldpt); + VectorCopy2(pt2, oldpt2); + } + + // shuffle lathe points + VectorCopy2(l_oldpt2, l_oldpt); + } +} + +#define DISK_DEF 4 +#define TUBE_DEF 6 + +static void RB_SurfaceClouds() +{ + // Disk definition + float diskStripDef[DISK_DEF] = { + 0.0f, + 0.4f, + 0.7f, + 1.0f }; + + float diskAlphaDef[DISK_DEF] = { + 1.0f, + 1.0f, + 0.4f, + 0.0f }; + + float diskCurveDef[DISK_DEF] = { + 0.0f, + 0.0f, + 0.008f, + 0.02f }; + + // tube definition + float tubeStripDef[TUBE_DEF] = { + 0.0f, + 0.05f, + 0.1f, + 0.5f, + 0.7f, + 1.0f }; + + float tubeAlphaDef[TUBE_DEF] = { + 0.0f, + 0.45f, + 1.0f, + 1.0f, + 0.45f, + 0.0f }; + + float tubeCurveDef[TUBE_DEF] = { + 0.0f, + 0.004f, + 0.006f, + 0.01f, + 0.006f, + 0.0f }; + + refEntity_t *e; + vec3_t pt, oldpt; + vec3_t pt2, oldpt2; + float latheStep = 30.0f; + float s, c, temp; + float *stripDef, *alphaDef, *curveDef, ct; + int i, t, vbase; + + e = &backEnd.currentEntity->e; + + // select which type we shall be doing + if (e->renderfx & RF_GROW) // doing tube type + { + ct = TUBE_DEF; + stripDef = tubeStripDef; + alphaDef = tubeAlphaDef; + curveDef = tubeCurveDef; + e->backlerp *= -1; // needs to be reversed + } + else + { + ct = DISK_DEF; + stripDef = diskStripDef; + alphaDef = diskAlphaDef; + curveDef = diskCurveDef; + } + + // do the strip def, then lathe this around to make a 3d model + for (i = 0; i < ct - 1; i++) + { + VectorSet(oldpt, (stripDef[i] * (e->radius - e->rotation)) + e->rotation, 0, curveDef[i] * e->radius * e->backlerp); + VectorSet(oldpt2, (stripDef[i + 1] * (e->radius - e->rotation)) + e->rotation, 0, curveDef[i + 1] * e->radius * e->backlerp); + + // lathe section around in a complete circle + for (t = latheStep; t <= 360; t += latheStep) + { + // rotate every time except last seg + if (t < 360.0f) + { + VectorCopy(oldpt, pt); + VectorCopy(oldpt2, pt2); + + s = sin(DEG2RAD(latheStep)); + c = cos(DEG2RAD(latheStep)); + + // rotate lathe points + temp = c * pt[0] - s * pt[1]; // c -s 0 + pt[1] = s * pt[0] + c * pt[1]; // s c 0 + pt[0] = temp; // 0 0 1 + + temp = c * pt2[0] - s * pt2[1]; // c -s 0 + pt2[1] = s * pt2[0] + c * pt2[1];// s c 0 + pt2[0] = temp; // 0 0 1 + } + else + { + // just glue directly to the def points. + VectorSet(pt, (stripDef[i] * (e->radius - e->rotation)) + e->rotation, 0, curveDef[i] * e->radius * e->backlerp); + VectorSet(pt2, (stripDef[i + 1] * (e->radius - e->rotation)) + e->rotation, 0, curveDef[i + 1] * e->radius * e->backlerp); + } + + RB_CHECKOVERFLOW(4, 6); + + vbase = tess.numVertexes; + + // Actually generate the necessary verts + VectorAdd(e->origin, oldpt, tess.xyz[tess.numVertexes]); + tess.texCoords[tess.numVertexes][0][0] = tess.xyz[tess.numVertexes][0] * 0.1f; + tess.texCoords[tess.numVertexes][0][1] = tess.xyz[tess.numVertexes][1] * 0.1f; + tess.vertexColors[tess.numVertexes][0] = + tess.vertexColors[tess.numVertexes][1] = + tess.vertexColors[tess.numVertexes][2] = e->shaderRGBA[0] * alphaDef[i]; + tess.vertexColors[tess.numVertexes][3] = e->shaderRGBA[3]; + tess.numVertexes++; + + VectorAdd(e->origin, oldpt2, tess.xyz[tess.numVertexes]); + tess.texCoords[tess.numVertexes][0][0] = tess.xyz[tess.numVertexes][0] * 0.1f; + tess.texCoords[tess.numVertexes][0][1] = tess.xyz[tess.numVertexes][1] * 0.1f; + tess.vertexColors[tess.numVertexes][0] = + tess.vertexColors[tess.numVertexes][1] = + tess.vertexColors[tess.numVertexes][2] = e->shaderRGBA[0] * alphaDef[i + 1]; + tess.vertexColors[tess.numVertexes][3] = e->shaderRGBA[3]; + tess.numVertexes++; + + VectorAdd(e->origin, pt, tess.xyz[tess.numVertexes]); + tess.texCoords[tess.numVertexes][0][0] = tess.xyz[tess.numVertexes][0] * 0.1f; + tess.texCoords[tess.numVertexes][0][1] = tess.xyz[tess.numVertexes][1] * 0.1f; + tess.vertexColors[tess.numVertexes][0] = + tess.vertexColors[tess.numVertexes][1] = + tess.vertexColors[tess.numVertexes][2] = e->shaderRGBA[0] * alphaDef[i]; + tess.vertexColors[tess.numVertexes][3] = e->shaderRGBA[3]; + tess.numVertexes++; + + VectorAdd(e->origin, pt2, tess.xyz[tess.numVertexes]); + tess.texCoords[tess.numVertexes][0][0] = tess.xyz[tess.numVertexes][0] * 0.1f; + tess.texCoords[tess.numVertexes][0][1] = tess.xyz[tess.numVertexes][1] * 0.1f; + tess.vertexColors[tess.numVertexes][0] = + tess.vertexColors[tess.numVertexes][1] = + tess.vertexColors[tess.numVertexes][2] = e->shaderRGBA[0] * alphaDef[i + 1]; + tess.vertexColors[tess.numVertexes][3] = e->shaderRGBA[3]; + tess.numVertexes++; + + tess.indexes[tess.numIndexes++] = vbase; + tess.indexes[tess.numIndexes++] = vbase + 1; + tess.indexes[tess.numIndexes++] = vbase + 3; + + tess.indexes[tess.numIndexes++] = vbase + 3; + tess.indexes[tess.numIndexes++] = vbase + 2; + tess.indexes[tess.numIndexes++] = vbase; + + // Shuffle new points to old + VectorCopy2(pt, oldpt); + VectorCopy2(pt2, oldpt2); + } + } +} /* =========================================================================== @@ -2022,15 +2396,15 @@ static void RB_SurfaceEntity( surfaceType_t *surfType ) { case RT_LINE: RB_SurfaceLine(); break; - case RT_ORIENTEDLINE: - RB_SurfaceOrientedLine(); - break; case RT_SABER_GLOW: RB_SurfaceSaberGlow(); break; case RT_CYLINDER: RB_SurfaceCylinder(); break; + case RT_ORIENTEDLINE: + RB_SurfaceOrientedLine(); + break; case RT_ENT_CHAIN: { static trRefEntity_t tempEnt = *backEnd.currentEntity; @@ -2055,6 +2429,12 @@ static void RB_SurfaceEntity( surfaceType_t *surfType ) { } } break; + case RT_LATHE: + RB_SurfaceLathe(); + break; + case RT_CLOUDS: + RB_SurfaceClouds(); + break; default: RB_SurfaceAxis(); break; @@ -2094,7 +2474,12 @@ void RB_SurfaceVBOMDVMesh(srfVBOMDVMesh_t * surface) RB_EndSurface(); } - //drawSurf_t drawSurf = + //FIXME: Implement GPU vertex interpolation instead! + if (backEnd.currentEntity->e.oldframe != 0 || backEnd.currentEntity->e.frame != 0) + { + RB_SurfaceMesh(surface->mdvSurface); + return; + } R_BindVBO(surface->vbo); R_BindIBO(surface->ibo); @@ -2205,8 +2590,8 @@ static void RB_SurfaceSprites( srfSprites_t *surf ) const surfaceSprite_t *ss = surf->sprite; uint32_t shaderFlags = 0; - if ( surf->alphaTestType != ALPHA_TEST_NONE ) - shaderFlags |= SSDEF_ALPHA_TEST; + /*if ( surf->alphaTestType != ALPHA_TEST_NONE ) + shaderFlags |= SSDEF_ALPHA_TEST;*/ if ( ss->type == SURFSPRITE_ORIENTED ) shaderFlags |= SSDEF_FACE_CAMERA; @@ -2247,7 +2632,8 @@ static void RB_SurfaceSprites( srfSprites_t *surf ) SamplerBindingsWriter samplerBindingsWriter; samplerBindingsWriter.AddAnimatedImage(&firstStage->bundle[0], TB_COLORMAP); - const GLuint currentFrameUbo = backEndData->currentFrame->ubo; + const byte currentFrameScene = backEndData->currentFrame->currentScene; + const GLuint currentFrameUbo = backEndData->currentFrame->ubo[currentFrameScene]; const GLuint currentSpriteUbo = shader->spriteUbo; const UniformBlockBinding uniformBlockBindings[] = { { currentSpriteUbo, ss->spriteUboOffset, UNIFORM_BLOCK_SURFACESPRITE }, diff --git a/codemp/rd-rend2/tr_tangentspace.cpp b/shared/rd-rend2/tr_tangentspace.cpp similarity index 100% rename from codemp/rd-rend2/tr_tangentspace.cpp rename to shared/rd-rend2/tr_tangentspace.cpp diff --git a/codemp/rd-rend2/tr_vbo.cpp b/shared/rd-rend2/tr_vbo.cpp similarity index 91% rename from codemp/rd-rend2/tr_vbo.cpp rename to shared/rd-rend2/tr_vbo.cpp index 4025bd31d5..7627f68c0c 100644 --- a/codemp/rd-rend2/tr_vbo.cpp +++ b/shared/rd-rend2/tr_vbo.cpp @@ -91,7 +91,7 @@ VBO_t *R_CreateVBO(byte * vertexes, int vertexesSize, vboUsage_t usage) R_IssuePendingRenderCommands(); - vbo = tr.vbos[tr.numVBOs] = (VBO_t *)ri.Hunk_Alloc(sizeof(*vbo), h_low); + vbo = tr.vbos[tr.numVBOs] = (VBO_t *)Hunk_Alloc(sizeof(*vbo), h_low); memset(vbo, 0, sizeof(*vbo)); @@ -140,7 +140,7 @@ IBO_t *R_CreateIBO(byte * indexes, int indexesSize, vboUsage_t usage) R_IssuePendingRenderCommands(); - ibo = tr.ibos[tr.numIBOs] = (IBO_t *)ri.Hunk_Alloc(sizeof(*ibo), h_low); + ibo = tr.ibos[tr.numIBOs] = (IBO_t *)Hunk_Alloc(sizeof(*ibo), h_low); ibo->indexesSize = indexesSize; qglGenBuffers(1, &ibo->indexesVBO); @@ -686,7 +686,7 @@ void RB_UpdateGoreVBO(srfG2GoreSurface_t *goreSurface) goreSurface->firstVert = tr.goreVBOCurrentIndex; goreSurface->firstIndex = tr.goreIBOCurrentIndex; - if (tr.goreVBOCurrentIndex + goreSurface->numVerts >= (MAX_LODS * MAX_GORE_RECORDS * MAX_GORE_VERTS * MAX_FRAMES)) + if (tr.goreVBOCurrentIndex + goreSurface->numVerts >= (MAX_GORE_RECORDS * MAX_GORE_VERTS * MAX_FRAMES)) tr.goreVBOCurrentIndex = 0; R_BindVBO(tr.goreVBO); @@ -698,7 +698,7 @@ void RB_UpdateGoreVBO(srfG2GoreSurface_t *goreSurface) ); tr.goreVBOCurrentIndex += goreSurface->numVerts; - if (tr.goreIBOCurrentIndex + goreSurface->numVerts >= (MAX_LODS * MAX_GORE_RECORDS * MAX_GORE_INDECIES * MAX_FRAMES)) + if (tr.goreIBOCurrentIndex + goreSurface->numIndexes >= (MAX_GORE_RECORDS * MAX_GORE_INDECIES * MAX_FRAMES)) tr.goreIBOCurrentIndex = 0; R_BindIBO(tr.goreIBO); @@ -745,16 +745,17 @@ int RB_BindAndUpdateFrameUniformBlock(uniformBlock_t block, void *data) { const uniformBlockInfo_t *blockInfo = uniformBlocksInfo + block; gpuFrame_t *thisFrame = backEndData->currentFrame; - const int offset = thisFrame->uboWriteOffset; + const byte currentFrameScene = thisFrame->currentScene; + const int offset = thisFrame->uboWriteOffset[currentFrameScene]; - RB_BindUniformBlock(thisFrame->ubo, block, offset); + RB_BindUniformBlock(thisFrame->ubo[currentFrameScene], block, offset); qglBufferSubData(GL_UNIFORM_BUFFER, - thisFrame->uboWriteOffset, blockInfo->size, data); + thisFrame->uboWriteOffset[currentFrameScene], blockInfo->size, data); const int alignment = glRefConfig.uniformBufferOffsetAlignment - 1; const size_t alignedBlockSize = (blockInfo->size + alignment) & ~alignment; - thisFrame->uboWriteOffset += alignedBlockSize; + thisFrame->uboWriteOffset[currentFrameScene] += alignedBlockSize; return offset; } @@ -780,10 +781,11 @@ int RB_AddShaderInstanceBlock(void *data) void RB_BeginConstantsUpdate(gpuFrame_t *frame) { - if (glState.currentGlobalUBO != frame->ubo) + const byte currentFrameScene = frame->currentScene; + if (glState.currentGlobalUBO != frame->ubo[currentFrameScene]) { - qglBindBuffer(GL_UNIFORM_BUFFER, frame->ubo); - glState.currentGlobalUBO = frame->ubo; + qglBindBuffer(GL_UNIFORM_BUFFER, frame->ubo[currentFrameScene]); + glState.currentGlobalUBO = frame->ubo[currentFrameScene]; } const GLbitfield mapFlags = @@ -791,35 +793,37 @@ void RB_BeginConstantsUpdate(gpuFrame_t *frame) GL_MAP_UNSYNCHRONIZED_BIT | GL_MAP_FLUSH_EXPLICIT_BIT; - frame->uboMapBase = frame->uboWriteOffset; - frame->uboMemory = qglMapBufferRange( + frame->uboMapBase[currentFrameScene] = frame->uboWriteOffset[currentFrameScene]; + frame->uboMemory[currentFrameScene] = qglMapBufferRange( GL_UNIFORM_BUFFER, - frame->uboWriteOffset, - frame->uboSize - frame->uboWriteOffset, + frame->uboWriteOffset[currentFrameScene], + frame->uboSize[currentFrameScene] - frame->uboWriteOffset[currentFrameScene], mapFlags); } int RB_AppendConstantsData( gpuFrame_t *frame, const void *data, size_t dataSize) { - const size_t writeOffset = frame->uboWriteOffset; - const size_t relativeOffset = writeOffset - frame->uboMapBase; + const byte currentFrameScene = frame->currentScene; + const size_t writeOffset = frame->uboWriteOffset[currentFrameScene]; + const size_t relativeOffset = writeOffset - frame->uboMapBase[currentFrameScene]; - memcpy((char *)frame->uboMemory + relativeOffset, data, dataSize); + memcpy((char *)frame->uboMemory[currentFrameScene] + relativeOffset, data, dataSize); const int alignment = glRefConfig.uniformBufferOffsetAlignment - 1; const size_t alignedBlockSize = (dataSize + alignment) & ~alignment; - frame->uboWriteOffset += alignedBlockSize; - assert(frame->uboWriteOffset > 0); + frame->uboWriteOffset[currentFrameScene] += alignedBlockSize; + assert(frame->uboWriteOffset[currentFrameScene] > 0); return writeOffset; } void RB_EndConstantsUpdate(const gpuFrame_t *frame) { + const byte currentFrameScene = frame->currentScene; qglFlushMappedBufferRange( GL_UNIFORM_BUFFER, - frame->uboMapBase, - frame->uboWriteOffset - frame->uboMapBase); + frame->uboMapBase[currentFrameScene], + frame->uboWriteOffset[currentFrameScene] - frame->uboMapBase[currentFrameScene]); qglUnmapBuffer(GL_UNIFORM_BUFFER); } \ No newline at end of file diff --git a/codemp/rd-rend2/tr_weather.cpp b/shared/rd-rend2/tr_weather.cpp similarity index 90% rename from codemp/rd-rend2/tr_weather.cpp rename to shared/rd-rend2/tr_weather.cpp index af070e72dd..009685dde9 100644 --- a/codemp/rd-rend2/tr_weather.cpp +++ b/shared/rd-rend2/tr_weather.cpp @@ -23,6 +23,9 @@ along with this program; if not, see . #include #include +// Cached to save test tume +int CurrentWeatherBrushIndex; + namespace { const int CHUNK_COUNT = 9; // in 3x3 arrangement @@ -169,8 +172,7 @@ namespace { FBO_Bind(tr.weatherDepthFbo); - qglViewport(0, 0, tr.weatherDepthFbo->width, tr.weatherDepthFbo->height); - qglScissor(0, 0, tr.weatherDepthFbo->width, tr.weatherDepthFbo->height); + GL_SetViewportAndScissor(0, 0, tr.weatherDepthFbo->width, tr.weatherDepthFbo->height); if (tr.weatherSystem->weatherBrushType == WEATHER_BRUSHES_OUTSIDE) // used outside brushes { @@ -282,7 +284,6 @@ namespace // Now test if the intersected point is actually on the brush for (int j = 0; j < currentWeatherBrush->numPlanes; j++) { - vec4_t *plane = ¤tWeatherBrush->planes[j]; vec3_t normal = { currentWeatherBrush->planes[j][0], currentWeatherBrush->planes[j][1], @@ -439,7 +440,8 @@ namespace item.uniformData = uniformDataWriter.Finish(*backEndData->perFrameMemory); - const GLuint currentFrameUbo = backEndData->currentFrame->ubo; + const byte currentFrameScene = backEndData->currentFrame->currentScene; + const GLuint currentFrameUbo = backEndData->currentFrame->ubo[currentFrameScene]; const UniformBlockBinding uniformBlockBindings[] = { { currentFrameUbo, tr.sceneUboOffset, UNIFORM_BLOCK_SCENE } }; @@ -473,13 +475,16 @@ void R_InitWeatherSystem() { Com_Printf("Initializing weather system\n"); tr.weatherSystem = - (weatherSystem_t *)Z_Malloc(sizeof(*tr.weatherSystem), TAG_R_TERRAIN, qtrue); + (weatherSystem_t *)R_Malloc(sizeof(*tr.weatherSystem), TAG_R_TERRAIN, qtrue); tr.weatherSystem->weatherSurface.surfaceType = SF_WEATHER; tr.weatherSystem->frozen = false; + tr.weatherSystem->shaking = false; tr.weatherSystem->activeWeatherTypes = 0; tr.weatherSystem->constWindDirection[0] = .0f; tr.weatherSystem->constWindDirection[1] = .0f; + CurrentWeatherBrushIndex = -1; + for (int i = 0; i < NUM_WEATHER_TYPES; i++) tr.weatherSystem->weatherSlots[i].active = false; } @@ -547,15 +552,40 @@ void R_AddWeatherBrush(uint8_t numPlanes, vec4_t *planes) tr.weatherSystem->numWeatherBrushes++; } +void R_LoadWeatherImages() +{ + if (!tr.weatherSystem) + return; + + // Image flags and type + imgType_t type = IMGTYPE_COLORALPHA; + int flags = IMGFLAG_CLAMPTOEDGE; + if (tr.hdrLighting) + flags |= IMGFLAG_SRGB; + + if (tr.weatherSystem->weatherSlots[WEATHER_RAIN].active) + tr.weatherSystem->weatherSlots[WEATHER_RAIN].drawImage = R_FindImageFile("gfx/world/rain.jpg", type, flags); + if (tr.weatherSystem->weatherSlots[WEATHER_SNOW].active) + tr.weatherSystem->weatherSlots[WEATHER_SNOW].drawImage = R_FindImageFile("gfx/effects/snowflake1", type, flags); + if (tr.weatherSystem->weatherSlots[WEATHER_SPACEDUST].active) + tr.weatherSystem->weatherSlots[WEATHER_SPACEDUST].drawImage = R_FindImageFile("gfx/effects/snowpuff1", type, flags); + if (tr.weatherSystem->weatherSlots[WEATHER_SAND].active) + tr.weatherSystem->weatherSlots[WEATHER_SAND].drawImage = R_FindImageFile("gfx/effects/alpha_smoke2b", type, flags); + if (tr.weatherSystem->weatherSlots[WEATHER_FOG].active) + tr.weatherSystem->weatherSlots[WEATHER_FOG].drawImage = R_FindImageFile("gfx/effects/alpha_smoke2b", type, flags); +} + void RE_WorldEffectCommand(const char *command) { if (!command) { return; } - +#ifndef REND2_SP COM_BeginParseSession("RE_WorldEffectCommand"); - +#else + COM_BeginParseSession(); +#endif const char *token;//, *origCommand; token = COM_ParseExt(&command, qfalse); @@ -682,9 +712,7 @@ void RE_WorldEffectCommand(const char *command) tr.weatherSystem->weatherSlots[WEATHER_RAIN].velocityOrientationScale = 1.0f; - imgType_t type = IMGTYPE_COLORALPHA; - int flags = IMGFLAG_CLAMPTOEDGE; - tr.weatherSystem->weatherSlots[WEATHER_RAIN].drawImage = R_FindImageFile("gfx/world/rain.jpg", type, flags); + VectorSet4(tr.weatherSystem->weatherSlots[WEATHER_RAIN].color, 0.5f, 0.5f, 0.5f, 0.5f); VectorScale( @@ -720,10 +748,6 @@ void RE_WorldEffectCommand(const char *command) tr.weatherSystem->weatherSlots[WEATHER_RAIN].velocityOrientationScale = 1.0f; - imgType_t type = IMGTYPE_COLORALPHA; - int flags = IMGFLAG_CLAMPTOEDGE; - tr.weatherSystem->weatherSlots[WEATHER_RAIN].drawImage = R_FindImageFile("gfx/world/rain.jpg", type, flags); - VectorSet4(tr.weatherSystem->weatherSlots[WEATHER_RAIN].color, 0.5f, 0.5f, 0.5f, 0.5f); VectorScale( tr.weatherSystem->weatherSlots[WEATHER_RAIN].color, @@ -763,9 +787,7 @@ void RE_WorldEffectCommand(const char *command) tr.weatherSystem->weatherSlots[WEATHER_RAIN].velocityOrientationScale = 1.0f; - imgType_t type = IMGTYPE_COLORALPHA; - int flags = IMGFLAG_CLAMPTOEDGE; - tr.weatherSystem->weatherSlots[WEATHER_RAIN].drawImage = R_FindImageFile("gfx/world/rain.jpg", type, flags); + tr.weatherSystem->pain = 0.1f; VectorSet4(tr.weatherSystem->weatherSlots[WEATHER_RAIN].color, 0.34f, 0.7f, 0.34f, 0.7f); VectorScale( @@ -801,10 +823,6 @@ void RE_WorldEffectCommand(const char *command) tr.weatherSystem->weatherSlots[WEATHER_RAIN].velocityOrientationScale = 1.0f; - imgType_t type = IMGTYPE_COLORALPHA; - int flags = IMGFLAG_CLAMPTOEDGE; - tr.weatherSystem->weatherSlots[WEATHER_RAIN].drawImage = R_FindImageFile("gfx/world/rain", type, flags); - VectorSet4(tr.weatherSystem->weatherSlots[WEATHER_RAIN].color, 0.5f, 0.5f, 0.5f, 0.5f); VectorScale( tr.weatherSystem->weatherSlots[WEATHER_RAIN].color, @@ -834,10 +852,6 @@ void RE_WorldEffectCommand(const char *command) tr.weatherSystem->weatherSlots[WEATHER_SNOW].velocityOrientationScale = 0.0f; - imgType_t type = IMGTYPE_COLORALPHA; - int flags = IMGFLAG_CLAMPTOEDGE; - tr.weatherSystem->weatherSlots[WEATHER_SNOW].drawImage = R_FindImageFile("gfx/effects/snowflake1", type, flags); - VectorSet4(tr.weatherSystem->weatherSlots[WEATHER_SNOW].color, 0.75f, 0.75f, 0.75f, 0.75f); VectorScale( tr.weatherSystem->weatherSlots[WEATHER_SNOW].color, @@ -882,9 +896,7 @@ void RE_WorldEffectCommand(const char *command) tr.weatherSystem->weatherSlots[WEATHER_SPACEDUST].velocityOrientationScale = 0.0f; - imgType_t type = IMGTYPE_COLORALPHA; - int flags = IMGFLAG_CLAMPTOEDGE; - tr.weatherSystem->weatherSlots[WEATHER_SPACEDUST].drawImage = R_FindImageFile("gfx/effects/snowpuff1", type, flags); + VectorSet4(tr.weatherSystem->weatherSlots[WEATHER_SPACEDUST].color, 0.75f, 0.75f, 0.75f, 0.75f); VectorScale( @@ -926,10 +938,6 @@ void RE_WorldEffectCommand(const char *command) tr.weatherSystem->weatherSlots[WEATHER_SAND].velocityOrientationScale = 0.0f; - imgType_t type = IMGTYPE_COLORALPHA; - int flags = IMGFLAG_CLAMPTOEDGE; - tr.weatherSystem->weatherSlots[WEATHER_SAND].drawImage = R_FindImageFile("gfx/effects/alpha_smoke2b", type, flags); - VectorSet4(tr.weatherSystem->weatherSlots[WEATHER_SAND].color, 0.9f, 0.6f, 0.0f, 0.5f); } @@ -963,10 +971,6 @@ void RE_WorldEffectCommand(const char *command) tr.weatherSystem->weatherSlots[WEATHER_FOG].velocityOrientationScale = 0.0f; - imgType_t type = IMGTYPE_COLORALPHA; - int flags = IMGFLAG_CLAMPTOEDGE; - tr.weatherSystem->weatherSlots[WEATHER_FOG].drawImage = R_FindImageFile("gfx/effects/alpha_smoke2b", type, flags); - VectorSet4(tr.weatherSystem->weatherSlots[WEATHER_FOG].color, 0.2f, 0.2f, 0.2f, 0.2f); VectorScale(tr.weatherSystem->weatherSlots[WEATHER_FOG].color, 0.2f, tr.weatherSystem->weatherSlots[WEATHER_FOG].color); } @@ -1004,10 +1008,6 @@ void RE_WorldEffectCommand(const char *command) tr.weatherSystem->weatherSlots[WEATHER_FOG].velocityOrientationScale = 0.0f; - imgType_t type = IMGTYPE_COLORALPHA; - int flags = IMGFLAG_CLAMPTOEDGE; - tr.weatherSystem->weatherSlots[WEATHER_FOG].drawImage = R_FindImageFile("gfx/effects/alpha_smoke2b", type, flags); - VectorSet4(tr.weatherSystem->weatherSlots[WEATHER_FOG].color, 0.3f, 0.3f, 0.3f, 0.3f); VectorScale(tr.weatherSystem->weatherSlots[WEATHER_FOG].color, 0.3f, tr.weatherSystem->weatherSlots[WEATHER_FOG].color); } @@ -1045,21 +1045,25 @@ void RE_WorldEffectCommand(const char *command) tr.weatherSystem->weatherSlots[WEATHER_FOG].velocityOrientationScale = 0.0f; - imgType_t type = IMGTYPE_COLORALPHA; - int flags = IMGFLAG_CLAMPTOEDGE; - tr.weatherSystem->weatherSlots[WEATHER_FOG].drawImage = R_FindImageFile("gfx/effects/alpha_smoke2b", type, flags); - VectorSet4(tr.weatherSystem->weatherSlots[WEATHER_FOG].color, 0.19f, 0.6f, 0.7f, 0.12f); VectorScale(tr.weatherSystem->weatherSlots[WEATHER_FOG].color, 0.12f, tr.weatherSystem->weatherSlots[WEATHER_FOG].color); } else if (Q_stricmp(token, "outsideshake") == 0) { +#ifdef REND2_SP + tr.weatherSystem->shaking = true; +#else ri.Printf(PRINT_DEVELOPER, "outsideshake isn't supported in MP\n"); +#endif } else if (Q_stricmp(token, "outsidepain") == 0) { +#ifdef REND2_SP + tr.weatherSystem->pain = !tr.weatherSystem->pain; +#else ri.Printf(PRINT_DEVELOPER, "outsidepain isn't supported in MP\n"); +#endif } else { @@ -1085,6 +1089,11 @@ void RE_WorldEffectCommand(const char *command) ri.Printf(PRINT_ALL, " outsideshake\n"); // not available in MP ri.Printf(PRINT_ALL, " outsidepain\n"); // not available in MP } +#ifdef REND2_SP + COM_EndParseSession(); +#endif + if (tr.world) + R_LoadWeatherImages(); } void R_WorldEffect_f(void) @@ -1143,6 +1152,11 @@ void RB_SurfaceWeather( srfWeather_t *surf ) { chunkIndex = (int(centerZoneOffsetX + numMinZonesX) + x + 1) % 3; chunkIndex += (int(centerZoneOffsetY + numMinZonesY) + y + 1) % 3 * 3; + + if (chunkIndex < 0) { + chunkIndex += 9; + } + VectorSet2( zoneOffsets[chunkIndex], x, @@ -1219,7 +1233,8 @@ void RB_SurfaceWeather( srfWeather_t *surf ) { for (int x = -1; x <= 1; ++x, ++currentIndex) { - const GLuint currentFrameUbo = backEndData->currentFrame->ubo; + const byte currentFrameScene = backEndData->currentFrame->currentScene; + const GLuint currentFrameUbo = backEndData->currentFrame->ubo[currentFrameScene]; const UniformBlockBinding uniformBlockBindings[] = { { currentFrameUbo, tr.cameraUboOffsets[tr.viewParms.currentViewParm], UNIFORM_BLOCK_CAMERA } }; @@ -1256,3 +1271,123 @@ void RB_SurfaceWeather( srfWeather_t *surf ) } } } + +bool IsInsideBrush(const weatherBrushes_t* Brush, const vec3_t pos) +{ + // RBSP brushes actually store their bounding box in the first 6 planes! Nice + const vec3_t mins = { + -Brush->planes[0][3], + -Brush->planes[2][3], + -Brush->planes[4][3], + }; + const vec3_t maxs = { + Brush->planes[1][3], + Brush->planes[3][3], + Brush->planes[5][3], + }; + + return (pos[0] > mins[0] && pos[1] > mins[1] && pos[2] > mins[2] + && pos[0] < maxs[0] && pos[1] < maxs[1] && pos[2] < maxs[2]); +} + +bool R_IsOutside(vec3_t pos) +{ + if (!tr.weatherSystem) + { + return false; + } + + // check cashed brush first + if (CurrentWeatherBrushIndex >= 0 && CurrentWeatherBrushIndex < tr.weatherSystem->numWeatherBrushes) + { + if (IsInsideBrush(&tr.weatherSystem->weatherBrushes[CurrentWeatherBrushIndex], pos)) + { + return (tr.weatherSystem->weatherBrushType == WEATHER_BRUSHES_OUTSIDE); + } + } + + // check all weather brushes + for (int i = 0; i < tr.weatherSystem->numWeatherBrushes; i++) + { + const weatherBrushes_t* WeatherBrush = &tr.weatherSystem->weatherBrushes[i]; + + if (IsInsideBrush(WeatherBrush, pos)) + { + CurrentWeatherBrushIndex = i; + return (tr.weatherSystem->weatherBrushType == WEATHER_BRUSHES_OUTSIDE); + } + } + + CurrentWeatherBrushIndex = -1; + return (tr.weatherSystem->weatherBrushType != WEATHER_BRUSHES_OUTSIDE); +} + +bool R_IsShaking(vec3_t pos) +{ + return (tr.weatherSystem + && tr.weatherSystem->shaking + && R_IsOutside(pos)); +} + +bool R_GetWindVector(vec3_t windVector, vec3_t atPoint) +{ + // @TODO: need to process "Windzone" command + + if (!tr.weatherSystem) + { + return false; + } + + VectorCopy(tr.weatherSystem->windDirection, windVector); + VectorNormalize(windVector); + // everything is processed in RB_SurfaceWeather, no need to add something here + return (VectorLength(windVector) > 0.0f); +} + +bool R_GetWindGusting(vec3_t atPoint) +{ + if (!tr.weatherSystem) + return false; + + float windSpeed = VectorLength(tr.weatherSystem->windDirection); + return (windSpeed > 1.0f); +} + +float R_IsOutsideCausingPain(vec3_t pos) +{ + return (R_IsOutside(pos) && tr.weatherSystem->pain); +} + +float R_GetChanceOfSaberFizz() +{ + float chance = 0.0f; + int numWater = 0; + if (tr.weatherSystem->weatherSlots[WEATHER_RAIN].active) + { + chance += (tr.weatherSystem->weatherSlots[WEATHER_RAIN].gravity / 20.0f); + numWater++; + } + if (tr.weatherSystem->weatherSlots[WEATHER_SNOW].active) + { + chance += (tr.weatherSystem->weatherSlots[WEATHER_SNOW].gravity / 20.0f); + numWater++; + } + if (numWater) + { + return (chance / numWater); + } + return 0.0f; +} + +bool R_IsRaining() +{ + if (!tr.weatherSystem) + return false; + + return tr.weatherSystem->weatherSlots[WEATHER_RAIN].active; +} + +bool R_IsPuffing() +{ + return false; +} \ No newline at end of file diff --git a/codemp/rd-rend2/tr_weather.h b/shared/rd-rend2/tr_weather.h similarity index 87% rename from codemp/rd-rend2/tr_weather.h rename to shared/rd-rend2/tr_weather.h index b03b25275d..3ac889c455 100644 --- a/codemp/rd-rend2/tr_weather.h +++ b/shared/rd-rend2/tr_weather.h @@ -100,6 +100,8 @@ struct weatherSystem_t int activeWindObjects = 0; int numWeatherBrushes = 0; bool frozen; + bool shaking; + float pain = 0.0f; srfWeather_t weatherSurface; @@ -115,7 +117,15 @@ void R_InitWeatherSystem(); void R_InitWeatherForMap(); void R_AddWeatherSurfaces(); void R_AddWeatherBrush(uint8_t numPlanes, vec4_t *planes); +void R_LoadWeatherImages(); void R_ShutdownWeatherSystem(); void RB_SurfaceWeather( srfWeather_t *surfaceType ); - +bool R_IsOutside(vec3_t pos); +bool R_IsShaking(vec3_t pos); +float R_IsOutsideCausingPain(vec3_t pos); +float R_GetChanceOfSaberFizz(); +bool R_GetWindVector(vec3_t windVector, vec3_t atPoint); // doesn't work? +bool R_GetWindGusting(vec3_t atPoint); // doesn't work + +void RE_WorldEffectCommand(const char *cmd); void R_WorldEffect_f(void); diff --git a/codemp/rd-rend2/tr_world.cpp b/shared/rd-rend2/tr_world.cpp similarity index 98% rename from codemp/rd-rend2/tr_world.cpp rename to shared/rd-rend2/tr_world.cpp index 01a84dc0d9..f07a0e6ddd 100644 --- a/codemp/rd-rend2/tr_world.cpp +++ b/shared/rd-rend2/tr_world.cpp @@ -757,19 +757,19 @@ static const byte *R_ClusterPVS (int cluster) { R_inPVS ================= */ +#ifndef REND2_SP qboolean R_inPVS( const vec3_t p1, const vec3_t p2, byte *mask ) { - int leafnum; - int cluster; - - leafnum = ri.CM_PointLeafnum (p1); - cluster = ri.CM_LeafCluster (leafnum); +#else +qboolean R_inPVS(vec3_t p1, vec3_t p2) { + byte *mask; +#endif + mnode_t* leaf = R_PointInLeaf(p1); //agh, the damn snapshot mask doesn't work for this - mask = (byte *) ri.CM_ClusterPVS (cluster); + mask = (byte *) ri.CM_ClusterPVS (leaf->cluster); - leafnum = ri.CM_PointLeafnum (p2); - cluster = ri.CM_LeafCluster (leafnum); - if ( !(mask[cluster>>3] & (1<<(cluster&7))) ) + leaf = R_PointInLeaf(p2); + if ( !(mask[leaf->cluster>>3] & (1<<(leaf->cluster&7))) ) return qfalse; return qtrue; @@ -833,7 +833,7 @@ void R_MarkLeaves( void ) const byte *vis = R_ClusterPVS(tr.visClusters[tr.visIndex]); int i; - for (i = 0, leaf = (tr.world->nodes + tr.world->numDecisionNodes); i < (tr.world->numnodes - tr.world->numDecisionNodes); i++, leaf++) { + for (i = 0, leaf = tr.world->nodes; i < tr.world->numnodes; i++, leaf++) { cluster = leaf->cluster; if ( cluster < 0 || cluster >= tr.world->numClusters ) { continue;