From 7df48151d4d59955850fc7bfda1d5e7186ae580c Mon Sep 17 00:00:00 2001 From: Kawe Mazidjatari <48657826+Mauler125@users.noreply.github.com> Date: Mon, 2 May 2022 03:13:39 +0200 Subject: [PATCH] Some 'BuildPropStaticFrustumCullMap' improvements Artifact problem for large maps is still not solved. --- r5dev/bsplib/bsplib.cpp | 124 ++++++++++++++++------------------ r5dev/bsplib/bsplib.h | 35 ++++++---- r5dev/public/include/studio.h | 105 +++++++++++++++++++++++++++- 3 files changed, 183 insertions(+), 81 deletions(-) diff --git a/r5dev/bsplib/bsplib.cpp b/r5dev/bsplib/bsplib.cpp index 79c66334..e87b236c 100644 --- a/r5dev/bsplib/bsplib.cpp +++ b/r5dev/bsplib/bsplib.cpp @@ -25,8 +25,8 @@ __int64 __fastcall BuildPropStaticFrustumCullMap(__int64 a1, __int64 a2, unsigne char v10; // r13 double v11; // xmm7_8 __int64 v12; // rsi - __int64 v13; // rdx - __int64 v14; // rbx + MDLHandle_t mdlhandle; // dx + studiohdr_t* studio; // rbx unsigned __int8 v15; // r8 const char* v16; // rax int v17; // eax @@ -54,7 +54,7 @@ __int64 __fastcall BuildPropStaticFrustumCullMap(__int64 a1, __int64 a2, unsigne unsigned __int64 v39; // rcx __int64 v40; // rax float v41; // xmm2_4 - __int64 v42; // rbx + studiohdr_t* v42; // rbx float v43; // xmm2_4 float v44; // xmm4_4 __m128i v45; // xmm1 @@ -74,27 +74,27 @@ __int64 __fastcall BuildPropStaticFrustumCullMap(__int64 a1, __int64 a2, unsigne __int64 v59; // rax __int64 v60; // r13 int v61; // eax - unsigned __int64 v62; // r13 + char* v62; // r13 __int64 v63; // rdx int v64; // er14 - unsigned __int64 v65; // rdi + char* v65; // rdi __int64 v66; // r13 __int64 v67; // r15 void* v68; // rbx - __int64 v69; // rcx + int32_t v69; // rcx __int64 result; // rax __m128i v71; // [rsp+38h] [rbp-D0h] BYREF - __int64 v72; // [rsp+48h] [rbp-C0h] + __int64 v72{}; // [rsp+48h] [rbp-C0h] __int64 v73; // [rsp+50h] [rbp-B8h] __m128 v74; // [rsp+58h] [rbp-B0h] BYREF - __int64 v75; // [rsp+68h] [rbp-A0h] + __int64 v75{}; // [rsp+68h] [rbp-A0h] __int64 v76; // [rsp+78h] [rbp-90h] __m128 v77[3]; // [rsp+88h] [rbp-80h] BYREF char Destination[376]; // [rsp+B8h] [rbp-50h] BYREF __int64 v79; // [rsp+278h] [rbp+170h] int v82; // [rsp+288h] [rbp+180h] int v83; // [rsp+290h] [rbp+188h] - __int64 v84; // [rsp+298h] [rbp+190h] + studiohdr_t* v84; // [rsp+298h] [rbp+190h] __int64 v85; // [rsp+2A8h] [rbp+1A0h] v9 = 1.0; @@ -105,11 +105,11 @@ __int64 __fastcall BuildPropStaticFrustumCullMap(__int64 a1, __int64 a2, unsigne *(_QWORD*)&v11 = *(unsigned int*)(a5 + 24); v12 = a4 >> 1; *(float*)(a1 + 12) = 1.0 / (float)(*(float*)&v11 * *(float*)&v11); - v13 = *(unsigned __int16*)(a7 + 320); - *(_WORD*)a1 = v13; - v14 = (__int64)CMDLCache::FindMDL(g_MDLCache, v13, 0i64); - v84 = v14; - if ((*(_BYTE*)(v14 + 156) & 0x10) == 0 && (*dword_1696A9D20) < 100) + mdlhandle = *(unsigned __int16*)(a7 + 0x140); + *(MDLHandle_t*)a1 = mdlhandle; + studio = CMDLCache::FindMDL(g_MDLCache, mdlhandle, nullptr); + v84 = studio; + if ((studio->flags & STUDIOHDR_FLAGS_STATIC_PROP) == 0 && (*dword_1696A9D20) < 0x64) ++(*dword_1696A9D20); v15 = *(_BYTE*)(a5 + 30); if (v15 > 2u && (unsigned __int8)(v15 - 6) > 2u) @@ -121,7 +121,7 @@ __int64 __fastcall BuildPropStaticFrustumCullMap(__int64 a1, __int64 a2, unsigne v17 = *(unsigned __int8*)(a5 + 32); *(_BYTE*)(a1 + 4) = v17; v18 = v17; - v19 = v17 < *(_DWORD*)(v14 + 228); + v19 = v17 < studio->numskinfamilies; *(_BYTE*)(a1 + 5) = v15; if (!v19) v18 = 0; @@ -145,7 +145,7 @@ __int64 __fastcall BuildPropStaticFrustumCullMap(__int64 a1, __int64 a2, unsigne if (*(_WORD*)(a5 + 34) != 0xFFFF) v21 = *(_WORD*)(a5 + 34); *(_WORD*)(a1 + 2) = v21; - sub_1404365A0(v77, (const __m128i*)a5, (unsigned int*)(a5 + 12), v11); + sub_1404365A0(v77, (const __m128i*)a5, (__m128i*)(a5 + 12), v11); v22 = *qword_141744EA8; v23 = v77[0]; v24 = v77[1]; @@ -154,18 +154,15 @@ __int64 __fastcall BuildPropStaticFrustumCullMap(__int64 a1, __int64 a2, unsigne *(__m128*)(v26 + (*qword_141744EA8)) = v77[0]; *(__m128*)(v26 + v22 + 16) = v24; *(__m128*)(v26 + v22 + 32) = v25; - auto m1 = _mm_set_ps(0.003922, 0.003922, 0.003922, 0.003922); __m128i m2 = { 0 }; __m128i m3 = { 0 }; - v74 = _mm_mul_ps(_mm_cvtepi32_ps(_mm_unpacklo_epi16(_mm_unpacklo_epi8(_mm_cvtsi32_si128(*(_DWORD*)(a5 + 52)), m2), m3)), m1); + v74 = _mm_mul_ps(_mm_cvtepi32_ps(_mm_unpacklo_epi16(_mm_unpacklo_epi8(_mm_cvtsi32_si128(*(_DWORD*)(a5 + 52)), m2), m3)), (*xmmword_1415BD270)); v27 = sub_140270130(&v74); - *(__m128*)(v26 + (*qword_141744EA8) + 48) = v27; - sub_140257F20(&*(void**)off_141731448, a7, &v71, &v71.m128i_i8[12]); + *(__m128*)(v26 + (*qword_141744EA8) + 48) = v27;// DIFF 1 + (*((void(__fastcall**)(void**, __int64, __m128i*, __int8*))*(void**)off_141731448 + 10))(&*(void**)off_141731448, a7, &v71, &v71.m128i_i8[12]); sub_14028F170((__int64)&v74, (__int64)&v74.m128_i64[1] + 4, v77, &v71, (const __m128i*) & v71.m128i_i8[12]); - v72 = v71.m128i_i8[12]; // may be wrong v28 = *qword_141744EA0; v29 = 3 * v12; - v75 = (__int64)&v74.m128_i64[1] + 4; // may be wrong. v30 = v75; *(__m128*)((*qword_141744EA0) + 8 * v29) = v74; *(_QWORD*)(v28 + 8 * v29 + 16) = v30; @@ -181,7 +178,7 @@ __int64 __fastcall BuildPropStaticFrustumCullMap(__int64 a1, __int64 a2, unsigne v35 = *qword_141744EA0; *(__m128i*)((*qword_141744EA0) + 8 * v33) = v32; *(_QWORD*)(v35 + 8 * v33 + 16) = v72; - v36 = (*qword_141744EA8); + v36 = *qword_141744EA8; v37 = (unsigned __int64)(unsigned int)(v12 + 2 * v31) << 6; *(__m128*)(v34 + (*qword_141744EA8)) = v23; *(__m128*)(v34 + v36 + 16) = v24; @@ -203,13 +200,13 @@ __int64 __fastcall BuildPropStaticFrustumCullMap(__int64 a1, __int64 a2, unsigne v42 = v84; if (v41 <= 0.0) { - if ((*(_DWORD*)(v84 + 156) & 0x800) != 0) + if ((v84->flags & STUDIOHDR_FLAGS_NO_FORCED_FADE) != 0) { v41 = 227023.36; } else { - v43 = *(float*)(v84 + 364); + v43 = v84->fadeDist; if (v43 <= 0.0) v41 = fmaxf( (float)((float)(sqrt( @@ -226,7 +223,7 @@ __int64 __fastcall BuildPropStaticFrustumCullMap(__int64 a1, __int64 a2, unsigne } v44 = fmaxf(v41, 100.0); *(float*)(a1 + 16) = v44 * v44; - v45 = _mm_loadu_si32((unsigned int*)(v84 + 368)); //v45 = (__m128i)*(unsigned int*)(v84 + 368); + v45 = _mm_loadu_si32(&v84->gatherSize); if (*(float*)v45.m128i_i32 <= 0.0) { LOWORD(v48) = 0; @@ -249,81 +246,78 @@ __int64 __fastcall BuildPropStaticFrustumCullMap(__int64 a1, __int64 a2, unsigne v9 = staticProp_no_fade_scalar->GetFloat(); v53 = 0; *(float*)((*qword_141744E88) + 8i64 * a3) = v9 * (float)(1.0 / (float)(v52 * staticProp_gather_size_weight->GetFloat())); + v54 = *qword_141744E88; *(_BYTE*)((*qword_141744E88) + 8i64 * a3 + 4) &= 0xFEu; - *(_BYTE*)((*qword_141744E88) + 8i64 * a3 + 4) |= v44 >= 227023.363449684; + *(_BYTE*)(v54 + 8i64 * a3 + 4) |= v44 >= 227023.363449684; v55 = (__int64)CMDLCache::GetStudioMaterialGlue(g_MDLCache, *(unsigned __int16*)(a7 + 320)); // Gets some object containing pointer to 2 CMaterialGlue vtables. v56 = *(unsigned __int16*)(a5 + 0x20); v76 = *(__int64*)v55; - v57 = v84 + *(int*)(v84 + 232) + 2i64 * v56 * *(_DWORD*)(v84 + 224); + v57 = (__int64)v84 + 2 * v56 * v84->numskinref + v84->skinindex; v58 = 0; v85 = v57; v83 = 0; - if (*(int*)(v84 + 236) <= 0) + if (v84->numbodyparts <= 0) return 0i64; v59 = 0i64; v73 = 0i64; do { - v60 = v59 + *(int*)(v42 + 240); + v60 = v59 + v42->bodypartindex; v61 = 0; - v62 = v42 + v60; + v62 = (char*)v42 + v60; v82 = 0; - v74.m128_u64[0] = v62; - if (*(int*)(v62 + 4) > 0) + v74.m128_u64[0] = (unsigned __int64)v62; + if (*((int*)v62 + 1) > 0) { v63 = 0i64; v79 = 0i64; do { v64 = 0; - v65 = v62 + v63 + *(int*)(v62 + 12); - if (*(int*)(v65 + 76) > 0) + v65 = &v62[v63 + *((int*)v62 + 3)]; + if (*((int*)v65 + 19) > 0) { v66 = v76; v67 = 0i64; do { v68 = *(void**)(v66 + 8i64 * *(__int16*)(v57 + 2i64 * *(int*)(v67 + *(int*)(v65 + 80) + v65))); - - //if (v68 > (void*)0x10000 && v68 < (void*)0xFFFFFFFFF) // ??? HACK ??? CHANGE ASAP ??? + if (!(*(unsigned __int8(__fastcall**)(void*))(*(_QWORD*)v68 + 688i64))(v68)) { - if (!(*(unsigned __int8(__fastcall**)(void*))(*(_QWORD*)v68 + 688i64))(v68)) + if (!(*(unsigned __int8(__fastcall**)(void*))(*(_QWORD*)v68 + 256i64))(v68) && (*(unsigned __int8(__fastcall**)(void*))(*(_QWORD*)v68 + 248i64))(v68)) { - if (!(*(unsigned __int8(__fastcall**)(void*))(*(_QWORD*)v68 + 256i64))(v68) && (*(unsigned __int8(__fastcall**)(void*))(*(_QWORD*)v68 + 248i64))(v68)) + v69 = 0; + if (*dword_141744EE8) { - v69 = 0i64; - if (*dword_141744EE8) - { - // Compares equality of pointers to the CMaterial object - // between the current offset [v69] in the CStaticPropMgr buffer - // and that of v68 (obtained via operation in parent loop). + // Compares equality of pointers to the CMaterial object + // between the current offset [v69] in the CStaticPropMgr buffer + // and that of v68 (obtained via operation in parent loop). - while (*(&*(void**)off_141744E70 + v69 + 16) != v68) - { - v69++;// = (unsigned int)(v69 + 1); - - if (static_cast(v69) >= *dword_141744EE8) - goto LABEL_42; - } - } - else + while (*(&*(void**)off_141744E70 + v69 + 16) != v68) { - LABEL_42: - *(&*(void**)off_141744E70 + (*dword_141744EE8)++ + 16) = v68; + v69++;// = (unsigned int)(v69 + 1); + + if (static_cast(v69) >= *dword_141744EE8) + goto LABEL_42; } } - if ((*(unsigned __int8(__fastcall**)(void*))(*(_QWORD*)v68 + 168i64))(v68) && (*(unsigned int(__fastcall**)(void*, __int64))(*(_QWORD*)v68 + 144i64))(v68, 1i64)) - *(_BYTE*)(a1 + 5) |= 0x80u; - if (!(*(unsigned __int8(__fastcall**)(void*))(*(_QWORD*)v68 + 384i64))(v68) && (*(unsigned int(__fastcall**)(void*, __int64))(*(_QWORD*)v68 + 144i64))(v68, 21844i64)) - v53 |= 2u; - v53 |= (*(unsigned __int8(__fastcall**)(void*))(*(_QWORD*)v68 + 384i64))(v68) != 0; + else + { + LABEL_42: + *(&*(void**)off_141744E70 + (*dword_141744EE8)++ + 16) = v68; + } } + if ((*(unsigned __int8(__fastcall**)(void*))(*(_QWORD*)v68 + 168i64))(v68) && (*(unsigned int(__fastcall**)(void*, __int64))(*(_QWORD*)v68 + 144i64))(v68, 1i64)) + *(_BYTE*)(a1 + 5) |= 0x80u; + if (!(*(unsigned __int8(__fastcall**)(void*))(*(_QWORD*)v68 + 384i64))(v68) && (*(unsigned int(__fastcall**)(void*, __int64))(*(_QWORD*)v68 + 144i64))(v68, 21844i64)) + v53 |= 2u; + v53 |= (*(unsigned __int8(__fastcall**)(void*))(*(_QWORD*)v68 + 384i64))(v68) != 0; } v57 = v85; ++v64; v67 += 92i64; - } while (v64 < *(_DWORD*)(v65 + 76)); - v62 = v74.m128_u64[0]; + } while (v64 < *((_DWORD*)v65 + 19)); + v62 = (char*)v74.m128_u64[0]; v61 = v82; v63 = v79; } @@ -331,7 +325,7 @@ __int64 __fastcall BuildPropStaticFrustumCullMap(__int64 a1, __int64 a2, unsigne v63 += 136i64; v82 = v61; v79 = v63; - } while (v61 < *(_DWORD*)(v62 + 4)); + } while (v61 < *((_DWORD*)v62 + 1)); v42 = v84; v58 = v83; } @@ -339,7 +333,7 @@ __int64 __fastcall BuildPropStaticFrustumCullMap(__int64 a1, __int64 a2, unsigne v59 = v73 + 16; v83 = v58; v73 += 16i64; - } while (v58 < *(_DWORD*)(v42 + 236)); + } while (v58 < v42->numbodyparts); result = v53; if (v53) *(_BYTE*)(a1 + 5) &= 0x7Fu; diff --git a/r5dev/bsplib/bsplib.h b/r5dev/bsplib/bsplib.h index 27eb44c7..3726891a 100644 --- a/r5dev/bsplib/bsplib.h +++ b/r5dev/bsplib/bsplib.h @@ -4,21 +4,23 @@ inline CMemory p_BuildPropStaticFrustumCullMap; inline auto v_BuildPropStaticFrustumCullMap = p_BuildPropStaticFrustumCullMap.RCast<__int64(*)(__int64 a1, __int64 a2, unsigned int a3, unsigned int a4, __int64 a5, __int64 a6, __int64 a7)>(); -inline void** (*sub_1404365A0)(__m128*, const __m128i*, unsigned int*, double); -inline __m128 (*sub_140270130)(__m128*); -inline const __m128i* (*sub_14028F170)(__int64, __int64, __m128*, const __m128i*, const __m128i*); -inline int64_t(*sub_140257F20)(void*, __int64, __m128i*, __int8*); +inline void** (*sub_1404365A0)(__m128*, const __m128i*, __m128i*, double) = nullptr; +inline __m128 (*sub_140270130)(__m128*) = nullptr; +inline const __m128i* (*sub_14028F170)(__int64, __int64, __m128*, const __m128i*, const __m128i*) = nullptr; +inline int64_t(*sub_140257F20)(void*, __int64, __m128i*, __int8*) = nullptr; -inline uint32_t* dword_1696A9D20; -inline int32_t* dword_141744EBC; -inline int32_t* dword_141744EE8; +inline int32_t* dword_1696A9D20 = nullptr; +inline int32_t* dword_141744EBC = nullptr; +inline int32_t* dword_141744EE8 = nullptr; -inline int64_t* qword_141744EA8; -inline int64_t* qword_141744EA0; -inline uint64_t* qword_141744E88; +inline int64_t* qword_141744EA8 = nullptr; +inline int64_t* qword_141744EA0 = nullptr; +inline int64_t* qword_141744E88 = nullptr; -inline void* off_141744E70; -inline void* off_141731448; +inline __m128* xmmword_1415BD270 = nullptr; + +inline void* off_141744E70 = nullptr; +inline void* off_141731448 = nullptr; __int64 __fastcall BuildPropStaticFrustumCullMap(__int64 a1, __int64 a2, unsigned int a3, unsigned int a4, __int64 a5, __int64 a6, __int64 a7); @@ -40,6 +42,7 @@ class HBspLib : public IDetour std::cout << "| VAR: qword_141744EA8 : 0x" << std::hex << std::uppercase << qword_141744EA8 << std::setw(0) << " |" << std::endl; std::cout << "| VAR: qword_141744EA0 : 0x" << std::hex << std::uppercase << qword_141744EA0 << std::setw(0) << " |" << std::endl; std::cout << "| VAR: qword_141744E88 : 0x" << std::hex << std::uppercase << qword_141744E88 << std::setw(0) << " |" << std::endl; + std::cout << "| VAR: xmmword_1415BD270 : 0x" << std::hex << std::uppercase << xmmword_1415BD270 << std::setw(0) << " |" << std::endl; std::cout << "| VAR: off_141744E70 : 0x" << std::hex << std::uppercase << off_141744E70 << std::setw(0) << " |" << std::endl; std::cout << "| VAR: off_141731448 : 0x" << std::hex << std::uppercase << off_141731448 << std::setw(0) << " |" << std::endl; std::cout << "+----------------------------------------------------------------+" << std::endl; @@ -49,20 +52,22 @@ class HBspLib : public IDetour p_BuildPropStaticFrustumCullMap = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x48\x8B\xC4\x44\x89\x40\x18\x48\x89\x50\x10\x55"), "xxxxxxxxxxxx"); /*48 8B C4 44 89 40 18 48 89 50 10 55*/ v_BuildPropStaticFrustumCullMap = p_BuildPropStaticFrustumCullMap.RCast<__int64(*)(__int64, __int64, unsigned int, unsigned int, __int64, __int64, __int64)>(); - sub_1404365A0 = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x48\x8B\xC4\x48\x83\xEC\x78\xF3\x41\x0F\x10\x48\x00"), "xxxxxxxxxxxx?").RCast(); + sub_1404365A0 = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x48\x8B\xC4\x48\x83\xEC\x78\xF3\x41\x0F\x10\x48\x00"), "xxxxxxxxxxxx?").RCast(); sub_140270130 = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x48\x83\xEC\x28\x66\x0F\x6F\x15\x00\x00\x00\x00"), "xxxxxxxx????").RCast<__m128(*)(__m128*)>(); sub_14028F170 = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x48\x83\xEC\x58\xF3\x41\x0F\x7E\x11"), "xxxxxxxxx").RCast(); sub_140257F20 = g_mGameDll.FindPatternSIMD(reinterpret_cast("\x48\x89\x5C\x24\x00\x57\x48\x83\xEC\x20\x49\x8B\xD9\x49\x8B\xF8\x48\x85\xD2"), "xxxx?xxxxxxxxxxxxxx").RCast<__int64(*)(void*, __int64, __m128i*, __int8*)>(); } virtual void GetVar(void) const { - dword_1696A9D20 = p_BuildPropStaticFrustumCullMap.FindPattern("89 0D").ResolveRelativeAddressSelf(0x2, 0x6).RCast(); + dword_1696A9D20 = p_BuildPropStaticFrustumCullMap.FindPattern("89 0D").ResolveRelativeAddressSelf(0x2, 0x6).RCast(); dword_141744EBC = p_BuildPropStaticFrustumCullMap.Offset(0x200).FindPattern("44 8B").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); dword_141744EE8 = p_BuildPropStaticFrustumCullMap.Offset(0x550).FindPattern("8B 15").ResolveRelativeAddressSelf(0x2, 0x6).RCast(); qword_141744EA8 = p_BuildPropStaticFrustumCullMap.Offset(0x150).FindPattern("48 8B").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); qword_141744EA0 = p_BuildPropStaticFrustumCullMap.Offset(0x220).FindPattern("48 8B").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); - qword_141744E88 = p_BuildPropStaticFrustumCullMap.Offset(0x4E0).FindPattern("48 8B").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); + qword_141744E88 = p_BuildPropStaticFrustumCullMap.Offset(0x4E0).FindPattern("48 8B").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); + + xmmword_1415BD270 = p_BuildPropStaticFrustumCullMap.Offset(0x1A0).FindPattern("0F 59").ResolveRelativeAddressSelf(0x3, 0x7).RCast<__m128*>(); off_141744E70 = p_BuildPropStaticFrustumCullMap.Offset(0x550).FindPattern("4C 8D").ResolveRelativeAddressSelf(0x3, 0x7).RCast(); #if defined (GAMEDLL_S0) || defined (GAMEDLL_S1) diff --git a/r5dev/public/include/studio.h b/r5dev/public/include/studio.h index 3308fd38..aff7b578 100644 --- a/r5dev/public/include/studio.h +++ b/r5dev/public/include/studio.h @@ -2,6 +2,106 @@ #define STUDIO_H #include "mathlib/vector.h" +// This flag is set if no hitbox information was specified +#define STUDIOHDR_FLAGS_AUTOGENERATED_HITBOX ( 1 << 0 ) + +// NOTE: This flag is set at loadtime, not mdl build time so that we don't have to rebuild +// models when we change materials. +#define STUDIOHDR_FLAGS_USES_ENV_CUBEMAP ( 1 << 1 ) + +// Use this when there are translucent parts to the model but we're not going to sort it +#define STUDIOHDR_FLAGS_FORCE_OPAQUE ( 1 << 2 ) + +// Use this when we want to render the opaque parts during the opaque pass +// and the translucent parts during the translucent pass +#define STUDIOHDR_FLAGS_TRANSLUCENT_TWOPASS ( 1 << 3 ) + +// This is set any time the .qc files has $staticprop in it +// Means there's no bones and no transforms +#define STUDIOHDR_FLAGS_STATIC_PROP ( 1 << 4 ) + +// NOTE: This flag is set at loadtime, not mdl build time so that we don't have to rebuild +// models when we change materials. +#define STUDIOHDR_FLAGS_USES_FB_TEXTURE ( 1 << 5 ) + +// This flag is set by studiomdl.exe if a separate "$shadowlod" entry was present +// for the .mdl (the shadow lod is the last entry in the lod list if present) +#define STUDIOHDR_FLAGS_HASSHADOWLOD ( 1 << 6 ) + +// NOTE: This flag is set at loadtime, not mdl build time so that we don't have to rebuild +// models when we change materials. +#define STUDIOHDR_FLAGS_USES_BUMPMAPPING ( 1 << 7 ) + +// NOTE: This flag is set when we should use the actual materials on the shadow LOD +// instead of overriding them with the default one (necessary for translucent shadows) +#define STUDIOHDR_FLAGS_USE_SHADOWLOD_MATERIALS ( 1 << 8 ) + +// NOTE: This flag is set when we should use the actual materials on the shadow LOD +// instead of overriding them with the default one (necessary for translucent shadows) +#define STUDIOHDR_FLAGS_OBSOLETE ( 1 << 9 ) + +// NOTE: This flag is set when we need to draw in the additive stage of the deferred rendering +#define STUDIOHDR_FLAGS_NEEDS_DEFERRED_ADDITIVE ( 1 << 10 ) + +// NOTE: This flag is set at mdl build time +#define STUDIOHDR_FLAGS_NO_FORCED_FADE ( 1 << 11 ) + +// NOTE: The npc will lengthen the viseme check to always include two phonemes +#define STUDIOHDR_FLAGS_FORCE_PHONEME_CROSSFADE ( 1 << 12 ) + +// This flag is set when the .qc has $constantdirectionallight in it +// If set, we use constantdirectionallightdot to calculate light intensity +// rather than the normal directional dot product +// only valid if STUDIOHDR_FLAGS_STATIC_PROP is also set +#define STUDIOHDR_FLAGS_CONSTANT_DIRECTIONAL_LIGHT_DOT ( 1 << 13 ) + +// Flag to mark delta flexes as already converted from disk format to memory format +#define STUDIOHDR_FLAGS_FLEXES_CONVERTED ( 1 << 14 ) + +// Indicates the studiomdl was built in preview mode +#define STUDIOHDR_FLAGS_BUILT_IN_PREVIEW_MODE ( 1 << 15 ) + +// Ambient boost (runtime flag) +#define STUDIOHDR_FLAGS_AMBIENT_BOOST ( 1 << 16 ) + +// Don't cast shadows from this model (useful on first-person models) +#define STUDIOHDR_FLAGS_DO_NOT_CAST_SHADOWS ( 1 << 17 ) + +// alpha textures should cast shadows in vrad on this model (ONLY prop_static!) +#define STUDIOHDR_FLAGS_CAST_TEXTURE_SHADOWS ( 1 << 18 ) + +// Model has a quad-only Catmull-Clark SubD cage +#define STUDIOHDR_FLAGS_SUBDIVISION_SURFACE ( 1 << 19 ) + +// flagged on load to indicate no animation events on this model +#define STUDIOHDR_FLAGS_NO_ANIM_EVENTS ( 1 << 20 ) + +// If flag is set then studiohdr_t.flVertAnimFixedPointScale contains the +// scale value for fixed point vert anim data, if not set then the +// scale value is the default of 1.0 / 4096.0. Regardless use +// studiohdr_t::VertAnimFixedPointScale() to always retrieve the scale value +#define STUDIOHDR_FLAGS_VERT_ANIM_FIXED_POINT_SCALE ( 1 << 21 ) + +// If flag is set then model data is processed for EDGE +// the flag is set at tool time when producing PS3-format assets +#define STUDIOHDR_FLAGS_PS3_EDGE_FORMAT ( 1 << 22 ) + +// this is a specific case to indicate a model is over budget +#define STUDIOHDR_FLAGS_OVER_BUDGET ( 1 << 23 ) + +// this is a specific case to indicate a model is over budget +#define STUDIOHDR_FLAGS_IGNORE_BUDGETS ( 1 << 24 ) + +// internally generated combined model +#define STUDIOHDR_FLAGS_COMBINED ( 1 << 25 ) + +// Model has an additional set of UVs +#define STUDIOHDR_FLAGS_EXTRA_VERTEX_DATA ( 1 << 26 ) + +// NOTE: This flag is set at loadtime, not mdl build time so that we don't have to rebuild +// models when we change materials. +#define STUDIOHDR_BAKED_VERTEX_LIGHTING_IS_INDIRECT_ONLY ( 1 << 27 ) + #pragma pack(push, 1) struct studiohdr_t { @@ -61,7 +161,10 @@ struct studiohdr_t int submeshLodsIndex; - uint8_t Unknown3[0x64]; + uint8_t Unknown3[0x58]; + float fadeDist; + float gatherSize; + uint8_t Unknown4[0x4]; int boneRemapInfoIndex; int boneRemapCount; };