diff --git a/src/Components/Modules/QuickPatch.cpp b/src/Components/Modules/QuickPatch.cpp index b79bcdd0..34143914 100644 --- a/src/Components/Modules/QuickPatch.cpp +++ b/src/Components/Modules/QuickPatch.cpp @@ -973,6 +973,41 @@ namespace Components } }); + Dvar::OnInit([] + { + Dvar::Register("r_drawSceneModelBoundingBoxes", false, Game::DVAR_FLAG_CHEAT, "Draw scene model bounding boxes"); + }); + + Scheduler::OnFrame([]() + { + if (!Game::CL_IsCgameInitialized() || !Dvar::Var("r_drawSceneModelBoundingBoxes").get()) return; + + float red[4] = { 1.0f, 0.0f, 0.0f, 1.0f }; + float blue[4] = { 0.0f, 0.0f, 1.0f, 1.0f }; + + auto* scene = Game::scene; + + for(auto i = 0; i < scene->sceneModelCount; i++) + { + if(!scene->sceneModel[i].model) + continue; + + auto b = scene->sceneModel[i].model->bounds; + b.midPoint[0] += scene->sceneModel[i].placement.base.origin[0]; + b.midPoint[1] += scene->sceneModel[i].placement.base.origin[1]; + b.midPoint[2] += scene->sceneModel[i].placement.base.origin[2]; + b.halfSize[0] *= scene->sceneModel[i].placement.scale; + b.halfSize[1] *= scene->sceneModel[i].placement.scale; + b.halfSize[2] *= scene->sceneModel[i].placement.scale; + Game::R_AddDebugBounds(red, &b, &scene->sceneModel[i].placement.base.quat); + } + + for(auto i = 0; i < scene->sceneDObjCount; i++) + { + Game::R_AddDebugBounds(blue, &scene->sceneDObj[i].cull.bounds); + } + }); + // Dvars Dvar::Register("ui_streamFriendly", false, Game::DVAR_FLAG_SAVED, "Stream friendly UI"); diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index 63e01a18..14af16f0 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -419,6 +419,8 @@ namespace Game clientstate_t* clcState = reinterpret_cast(0xB2C540); + GfxScene* scene = reinterpret_cast(0x6944914); + XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize) { int elSize = DB_GetXAssetSizeHandlers[type](); @@ -728,6 +730,29 @@ namespace Game std::memmove(&solution[0], &res[0], sizeof(res)); } + void QuatRot(vec3_t* vec, const vec4_t* quat) + { + vec4_t q{ (*quat)[3],(*quat)[0],(*quat)[1],(*quat)[2] }; + + vec4_t res{ 0, (*vec)[0], (*vec)[1], (*vec)[2] }; + vec4_t res2; + vec4_t quat_conj{ q[0], -q[1], -q[2], -q[3] }; + QuatMultiply(&q, &res, &res2); + QuatMultiply(&res2, &quat_conj, &res); + + (*vec)[0] = res[1]; + (*vec)[1] = res[2]; + (*vec)[2] = res[3]; + } + + void QuatMultiply(const vec4_t* q1, const vec4_t* q2, vec4_t* res) + { + (*res)[0] = (*q2)[0] * (*q1)[0] - (*q2)[1] * (*q1)[1] - (*q2)[2] * (*q1)[2] - (*q2)[3] * (*q1)[3]; + (*res)[1] = (*q2)[0] * (*q1)[1] + (*q2)[1] * (*q1)[0] - (*q2)[2] * (*q1)[3] + (*q2)[3] * (*q1)[2]; + (*res)[2] = (*q2)[0] * (*q1)[2] + (*q2)[1] * (*q1)[3] + (*q2)[2] * (*q1)[0] - (*q2)[3] * (*q1)[1]; + (*res)[3] = (*q2)[0] * (*q1)[3] - (*q2)[1] * (*q1)[2] + (*q2)[2] * (*q1)[1] + (*q2)[3] * (*q1)[0]; + } + void SortWorldSurfaces(GfxWorld* world) { DWORD* specular1 = reinterpret_cast(0x69F105C); @@ -806,6 +831,73 @@ namespace Game Game::R_AddDebugLine(color, v4, v8); } + void R_AddDebugBounds(float* color, Bounds* b, const float(*quat)[4]) + { + vec3_t v[8]; + auto* center = b->midPoint; + auto* halfSize = b->halfSize; + + v[0][0] = -halfSize[0]; + v[0][1] = -halfSize[1]; + v[0][2] = -halfSize[2]; + + v[1][0] = halfSize[0]; + v[1][1] = -halfSize[1]; + v[1][2] = -halfSize[2]; + + v[2][0] = -halfSize[0]; + v[2][1] = halfSize[1]; + v[2][2] = -halfSize[2]; + + v[3][0] = halfSize[0]; + v[3][1] = halfSize[1]; + v[3][2] = -halfSize[2]; + + v[4][0] = -halfSize[0]; + v[4][1] = -halfSize[1]; + v[4][2] = halfSize[2]; + + v[5][0] = halfSize[0]; + v[5][1] = -halfSize[1]; + v[5][2] = halfSize[2]; + + v[6][0] = -halfSize[0]; + v[6][1] = halfSize[1]; + v[6][2] = halfSize[2]; + + v[7][0] = halfSize[0]; + v[7][1] = halfSize[1]; + v[7][2] = halfSize[2]; + + for(auto& vec : v) + { + QuatRot(&vec, quat); + vec[0] += center[0]; + vec[1] += center[1]; + vec[2] += center[2]; + } + + // bottom + Game::R_AddDebugLine(color, v[0], v[1]); + Game::R_AddDebugLine(color, v[1], v[3]); + Game::R_AddDebugLine(color, v[3], v[2]); + Game::R_AddDebugLine(color, v[2], v[0]); + + // top + Game::R_AddDebugLine(color, v[4], v[5]); + Game::R_AddDebugLine(color, v[5], v[7]); + Game::R_AddDebugLine(color, v[7], v[6]); + Game::R_AddDebugLine(color, v[6], v[4]); + + // verticals + Game::R_AddDebugLine(color, v[0], v[4]); + Game::R_AddDebugLine(color, v[1], v[5]); + Game::R_AddDebugLine(color, v[2], v[6]); + Game::R_AddDebugLine(color, v[3], v[7]); + } + + + #pragma optimize("", off) __declspec(naked) float UI_GetScoreboardLeft(void* /*a1*/) { diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 8b125c82..53d5b1f6 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -858,6 +858,8 @@ namespace Game extern clientstate_t* clcState; + extern GfxScene* scene; + XAssetHeader ReallocateAssetPool(XAssetType type, unsigned int newSize); void Menu_FreeItemMemory(Game::itemDef_s* item); const char* TableLookup(StringTable* stringtable, int row, int column); @@ -906,9 +908,12 @@ namespace Game void Vec3Normalize(vec3_t& vec); void Vec2UnpackTexCoords(const PackedTexCoords in, vec2_t* out); void MatrixVecMultiply(const float(&mulMat)[3][3], const vec3_t& mulVec, vec3_t& solution); + void QuatRot(vec3_t* vec, const vec4_t* quat); + void QuatMultiply(const vec4_t* q1, const vec4_t* q2, vec4_t* res); void SortWorldSurfaces(GfxWorld* world); void R_AddDebugLine(float* color, float* v1, float* v2); void R_AddDebugString(float *color, float *pos, float scale, const char *str); void R_AddDebugBounds(float* color, Bounds* b); + void R_AddDebugBounds(float* color, Bounds* b, const float(*quat)[4]); } diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index faa7f84d..bb17bf79 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -4844,6 +4844,278 @@ namespace Game GfxCmdBufState *state; }; + struct GfxDrawGroupSetupFields + { + unsigned __int16 materialSortedIndex : 15; + unsigned __int16 useHeroLighting : 1; + char sceneLightIndex; + char surfType; + }; + + union GfxDrawGroupSetup + { + GfxDrawGroupSetupFields fields; + unsigned int packed; + }; + + struct GfxMarkSurfLightingFields + { + char lmapIndex; + char reflectionProbeIndex; + unsigned __int16 modelIndex; + }; + + union GfxMarkSurfLighting + { + GfxMarkSurfLightingFields fields; + unsigned int packed; + }; + + struct GfxMarkSurf + { + GfxDrawGroupSetup drawGroup; + unsigned __int16* indices; + unsigned __int16 triCount; + char modelType; + char pad; + GfxMarkSurfLighting lighting; + }; + + struct GfxCodeSurf + { + GfxDrawGroupSetup drawGroup; + unsigned int triCount; + unsigned __int16* indices; + unsigned __int16 argOffset; + unsigned __int16 argCount; + }; + + struct __declspec(align(4)) GfxGlassSurf + { + GfxDrawGroupSetup drawGroup; + char pad; + char reflectionProbeIndex; + unsigned __int16 triCount; + unsigned __int16* indices; + unsigned __int16 lightingHandle; + }; + + struct GfxCloudSurfFields + { + unsigned __int16 materialSortedIndex; + char cloudDataIndex; + char surfType; + }; + + union GfxCloudSurf + { + GfxCloudSurfFields fields; + unsigned int packed; + }; + + struct GfxSparkSurfFields + { + unsigned __int16 materialSortedIndex; + unsigned __int16 sparkDataIndex; + }; + + union GfxSparkSurf + { + GfxSparkSurfFields fields; + unsigned int packed; + }; + + struct GfxSceneDef + { + int time; + float floatTime; + float viewOffset[3]; + GfxImage* sunShadowImage; + float sunShadowPixelAdjust[4]; + }; + + struct GfxLight + { + char type; + char canUseShadowMap; + char unused[2]; + float color[3]; + float dir[3]; + float origin[3]; + float radius; + float cosHalfFovOuter; + float cosHalfFovInner; + int exponent; + unsigned int spotShadowIndex; + GfxLightDef* def; + }; + + struct GfxVisibleLight + { + char pad[0x2004]; + }; + + struct GfxEntity + { + unsigned int renderFxFlags; + float materialTime; + }; + + struct GfxSkinnedXModelSurfs + { + void* firstSurf; + }; + + struct GfxSceneEntityCull + { + volatile unsigned int state; + Bounds bounds; + GfxSkinnedXModelSurfs skinnedSurfs; + }; + + union GfxSceneEntityInfo + { + void/*cpose_t*/* pose; + unsigned __int16* cachedLightingHandle; + }; + + struct GfxSceneEntity + { + float lightingOrigin[3]; + GfxPlacement placement; + GfxSceneEntityCull cull; + char lods[32]; + unsigned __int32 gfxEntIndex : 7; + unsigned __int32 entnum : 12; + unsigned __int32 renderFxFlags : 13; + void/*DObj*/* obj; + GfxSceneEntityInfo info; + char reflectionProbeIndex; + }; + + struct GfxScaledPlacement + { + GfxPlacement base; + float scale; + }; + + struct GfxSceneModel + { + XModelDrawInfo info; + XModel* model; + void/*DObj*/* obj; + GfxScaledPlacement placement; + unsigned __int32 gfxEntIndex : 7; + unsigned __int32 entnum : 12; + unsigned __int32 renderFxFlags : 13; + float radius; + unsigned __int16* cachedLightingHandle; + float lightingOrigin[3]; + char reflectionProbeIndex; + char lod; + }; + + struct __declspec(align(4)) GfxSceneBrush + { + BModelDrawInfo info; + unsigned __int16 entnum; + GfxBrushModel* bmodel; + GfxPlacement placement; + char reflectionProbeIndex; + }; + + union GfxSceneGlass + { + struct + { + bool rendered; + char reflectionProbeIndex; + unsigned __int16 lightingHandle; + }; + unsigned int packed; + }; + + union GfxEntCellRefInfo + { + float radius; + GfxBrushModel* bmodel; + }; + + struct GfxSceneDpvs + { + unsigned int localClientNum; + char* entVisData[7]; + unsigned __int16* sceneXModelIndex; + unsigned __int16* sceneDObjIndex; + GfxEntCellRefInfo* entInfo[4]; + }; + + struct __declspec(align(64)) GfxScene + { + GfxCodeSurf codeEmissiveSurfs[2048]; + GfxCodeSurf codeTransSurfs[640]; + GfxMarkSurf markSurfs[1536]; + GfxGlassSurf glassSurfs[768]; + GfxCloudSurf cloudSurfs[256]; + GfxDrawSurf drawSurfsDepthHack[32]; + GfxDrawSurf drawSurfsLitOpaque[8192]; + GfxDrawSurf drawSurfsLitTrans[2048]; + GfxDrawSurf drawSurfsEmissive[8192]; + GfxDrawSurf drawSurfsSunShadow0[4096]; + GfxDrawSurf drawSurfsSunShadow1[8192]; + GfxDrawSurf drawSurfsSpotShadow0[896]; + GfxDrawSurf drawSurfsSpotShadow1[896]; + GfxDrawSurf drawSurfsSpotShadow2[896]; + GfxDrawSurf drawSurfsSpotShadow3[896]; + unsigned int sceneLightIsUsed[32]; + unsigned int cachedSceneLightIsUsed[4][32]; + GfxSparkSurf sparkSurfs[64]; + unsigned int drawSurfLimit[10]; + volatile int drawSurfCount[10]; + GfxDrawSurf* drawSurfs[10]; + volatile int codeSurfUser[2]; + volatile int markMeshGuard; + unsigned int codeEmissiveSurfCount; + unsigned int codeTransSurfCount; + unsigned int markSurfCount; + unsigned int glassSurfCount; + GfxSceneDef def; + unsigned int addedLightCount; + GfxLight addedLight[32]; + bool isAddedLightCulled[32]; + float dynamicSpotLightNearPlaneOffset; + float dynamicSpotLightLength; + GfxVisibleLight visLight[4]; + GfxVisibleLight visLightShadow[1]; + unsigned int* entOverflowedDrawBuf; + volatile int gfxEntCount; + GfxEntity gfxEnts[128]; + int sceneDObjCount; + int preClientSceneDObjCount; + int sceneDObjCountAtMark; + GfxSceneEntity sceneDObj[520]; + char sceneDObjVisData[7][512]; + int sceneDObjMarkableViewmodelIndex; + unsigned int sceneDObjFirstViewmodelIndex; + unsigned int sceneDObjViewmodelCount; + volatile int sceneModelCount; + int sceneModelCountAtMark; + int sceneDObjModelCount; + GfxSceneModel sceneModel[1024]; + char sceneModelVisData[7][1024]; + volatile int sceneBrushCount; + int sceneBrushCountAtMark; + GfxSceneBrush sceneBrush[512]; + char sceneBrushVisData[3][512]; + GfxSceneGlass sceneGlass[1024]; + unsigned int sceneDynModelCount; + unsigned int sceneDynBrushCount; + int gfxEntCountAtMark; + GfxSceneDpvs dpvs; + int updateSound; + int allowAddDObj; + }; + #pragma endregion #ifndef IDA