Mercurial > mm7
diff Render.cpp @ 2464:104fdbea0386
cleaning project part 2
author | zipi |
---|---|
date | Sun, 17 Aug 2014 17:49:34 +0100 |
parents | 0f17a30149ec |
children | b054ea5daf45 |
line wrap: on
line diff
--- a/Render.cpp Sun Aug 17 15:13:18 2014 +0100 +++ b/Render.cpp Sun Aug 17 17:49:34 2014 +0100 @@ -3,7 +3,8 @@ #include <crtdbg.h> #define _CRT_SECURE_NO_WARNINGS -#include "mm7_unsorted_subs.h" +#include "VectorTypes.h" + #include "ZlibWrapper.h" #include "ErrorHandling.h" @@ -38,6 +39,8 @@ #include "Level/Decoration.h" #include "Vis.h" #include "Registry.h" +#include "Weather.h" + //#pragma comment(lib, "lib\\legacy_dx\\lib\\ddraw.lib") //#pragma comment(lib, "lib\\legacy_dx\\lib\\dxguid.lib") @@ -9524,3 +9527,2079 @@ + (__PAIR__(v10, (unsigned __int16)a4 >> 2) & 0x1C00)); } +//----- (0047C4FC) -------------------------------------------------------- +int __fastcall GetActorTintColor(int max_dimm, int min_dimm, float distance, int a4, RenderBillboard *a5) +{ + //int v5; // esi@1 + signed int v6; // edx@1 + //signed int result; // eax@2 + int v8; // eax@3 + double v9; // st7@12 + //double v10; // ST0C_8@18 + int v11; // ecx@28 + //signed int v12; // edi@28 + //double v13; // ST0C_8@33 + //double v14; // ST0C_8@34 + double v15; // st7@44 + //double v16; // ST0C_8@44 + //double v17; // ST0C_8@44 + int v18; // ST14_4@44 + //double v19; // ST0C_8@44 + signed int v20; // [sp+10h] [bp-4h]@10 + // float a3a; // [sp+1Ch] [bp+8h]@33 + //float a3b; // [sp+1Ch] [bp+8h]@34 + float a3c; // [sp+1Ch] [bp+8h]@44 + //float a3d; // [sp+1Ch] [bp+8h]@44 + //float a4b; // [sp+20h] [bp+Ch]@18 + //int a4a; // [sp+20h] [bp+Ch]@33 + //float a4c; // [sp+20h] [bp+Ch]@44 + //float a4d; // [sp+20h] [bp+Ch]@44 + int a5a; // [sp+24h] [bp+10h]@44 + + //v5 = a2; + v6 = 0; + + if (uCurrentlyLoadedLevelType == LEVEL_Indoor) + return 8 * (31 - max_dimm) | ((8 * (31 - max_dimm) | ((31 - max_dimm) << 11)) << 8); + + if (pParty->armageddon_timer) + return 0xFFFF0000; + + v8 = pWeather->bNight; + if (bUnderwater) + v8 = 0; + if (v8) + { + v20 = 1; + if ((signed __int64)pParty->pPartyBuffs[PARTY_BUFF_TORCHLIGHT].uExpireTime > 0) + v20 = pParty->pPartyBuffs[PARTY_BUFF_TORCHLIGHT].uPower; + v9 = (double)v20 * 1024.0; + if (a4) + { + v6 = 216; + goto LABEL_20; + } + if (distance <= v9) + { + if (distance > 0.0) + { + //a4b = distance * 216.0 / v9; + //v10 = a4b + 6.7553994e15; + //v6 = LODWORD(v10); + v6 = floorf(0.5f + distance * 216.0 / v9); + if (v6 > 216) + { + v6 = 216; + goto LABEL_20; + } + } + } + else + { + v6 = 216; + } + if (distance != 0.0) + { + LABEL_20: + if (a5) + v6 = 8 * _43F55F_get_billboard_light_level(a5, v6 >> 3); + if (v6 > 216) + v6 = 216; + return (255 - v6) | ((255 - v6) << 16) | ((255 - v6) << 8); + } + //LABEL_19: + v6 = 216; + goto LABEL_20; + } + + + + if (fabsf(distance) < 1.0e-6f) + return 0xFFF8F8F8; + + // dim in measured in 8-steps + v11 = 8 * (max_dimm - min_dimm); + //v12 = v11; + if (v11 >= 0) + { + if (v11 > 216) + v11 = 216; + } + else + v11 = 0; + + float fog_density_mult = 216.0f; + if (a4) + fog_density_mult += distance / (double)pODMRenderParams->shading_dist_shade * 32.0; + + v6 = v11 + floorf(pOutdoor->fFogDensity * fog_density_mult + 0.5f); + /*if ( a4 ) + { + //a3b = pOutdoor->fFogDensity * 216.0; + //v14 = a3b + 6.7553994e15; + //a4a = floorf(a3b + 0.5f);//LODWORD(v14); + } + else + { + //a3a = (distance / (double)pODMRenderParams->shading_dist_shade * 32.0 + 216.0) * pOutdoor->fFogDensity; + //v13 = a3a + 6.7553994e15; + //a4a = floorf(a3a + 0.5f);//LODWORD(v13); + } + v6 = a4a + v11;*/ + if (a5) + v6 = 8 * _43F55F_get_billboard_light_level(a5, v6 >> 3); + if (v6 > 216) + v6 = 216; + if (v6 < v11) + v6 = v11; + if (v6 > 8 * pOutdoor->max_terrain_dimming_level) + v6 = 8 * pOutdoor->max_terrain_dimming_level; + if (!bUnderwater) + return (255 - v6) | ((255 - v6) << 16) | ((255 - v6) << 8); + else + { + v15 = (double)(255 - v6) * 0.0039215689; + a3c = v15; + //a4c = v15 * 16.0; + //v16 = a4c + 6.7553994e15; + a5a = floorf(v15 * 16.0 + 0.5f);//LODWORD(v16); + //a4d = a3c * 194.0; + //v17 = a4d + 6.7553994e15; + v18 = floorf(a3c * 194.0 + 0.5f);//LODWORD(v17); + //a3d = a3c * 153.0; + //v19 = a3d + 6.7553994e15; + return (int)floorf(a3c * 153.0 + 0.5f)/*LODWORD(v19)*/ | ((v18 | (a5a << 8)) << 8); + } +} +// 6BE3C4: using guessed type char bUnderwater; + +//----- (0043F55F) -------------------------------------------------------- +int __fastcall _43F55F_get_billboard_light_level(RenderBillboard *a1, int uBaseLightLevel) +{ + signed int v3; // ecx@2 + + if (uCurrentlyLoadedLevelType == LEVEL_Indoor) + v3 = pIndoor->pSectors[a1->uIndoorSectorID].uMinAmbientLightLevel; + else + { + if (uBaseLightLevel == -1) + v3 = a1->dimming_level; + else + v3 = uBaseLightLevel; + } + return _43F5C8_get_point_light_level_with_respect_to_lights(v3, a1->uIndoorSectorID, a1->world_x, a1->world_y, a1->world_z); +} + +//----- (0043F5C8) -------------------------------------------------------- +int __fastcall _43F5C8_get_point_light_level_with_respect_to_lights(unsigned int uBaseLightLevel, int uSectorID, float x, float y, float z) +{ + // int v5; // esi@1 + signed int v6; // edi@1 + int v8; // eax@6 + int v9; // ebx@6 + unsigned int v10; // ecx@6 + unsigned int v11; // edx@9 + unsigned int v12; // edx@11 + signed int v13; // ecx@12 + BLVLightMM7 *v16; // esi@20 + int v17; // ebx@21 + // int v18; // eax@24 + // int v19; // ebx@24 + // unsigned int v20; // ecx@24 + // int v21; // edx@25 + // unsigned int v22; // edx@27 + // unsigned int v23; // edx@29 + signed int v24; // ecx@30 + int v26; // ebx@35 + // int v27; // eax@38 + // int v28; // ebx@38 + // unsigned int v29; // ecx@38 + // int v30; // edx@39 + // unsigned int v31; // edx@41 + // unsigned int v32; // edx@43 + //signed int v33; // ecx@44 + int v37; // [sp+Ch] [bp-18h]@37 + // int v38; // [sp+10h] [bp-14h]@5 + int v39; // [sp+10h] [bp-14h]@23 + int v40; // [sp+10h] [bp-14h]@36 + int v42; // [sp+14h] [bp-10h]@22 + unsigned int v43; // [sp+18h] [bp-Ch]@12 + unsigned int v44; // [sp+18h] [bp-Ch]@30 + unsigned int v45; // [sp+18h] [bp-Ch]@44 + + v6 = uBaseLightLevel; + for (uint i = 0; i < pMobileLightsStack->uNumLightsActive; ++i) + { + MobileLight* p = &pMobileLightsStack->pLights[i]; + + float distX = abs(p->vPosition.x - x); + if (distX <= p->uRadius) + { + float distY = abs(p->vPosition.y - y); + if (distY <= p->uRadius) + { + float distZ = abs(p->vPosition.z - z); + if (distZ <= p->uRadius) + { + v8 = distX; + v9 = distY; + v10 = distZ; + if (distX < distY) + { + v8 = distY; + v9 = distX; + } + if (v8 < distZ) + { + v11 = v8; + v8 = distZ; + v10 = v11; + } + if (v9 < (signed int)v10) + { + v12 = v10; + v10 = v9; + v9 = v12; + } + v43 = ((unsigned int)(11 * v9) / 32) + (v10 / 4) + v8; + v13 = p->uRadius; + if ((signed int)v43 < v13) + v6 += ((unsigned __int64)(30i64 * (signed int)(v43 << 16) / v13) >> 16) - 30; + } + } + } + } + + if (uCurrentlyLoadedLevelType == LEVEL_Indoor) + { + BLVSector* pSector = &pIndoor->pSectors[uSectorID]; + + for (uint i = 0; i < pSector->uNumLights; ++i) + { + v16 = pIndoor->pLights + pSector->pLights[i]; + if (~v16->uAtributes & 8) + { + v17 = abs(v16->vPosition.x - x); + if (v17 <= v16->uRadius) + { + v42 = abs(v16->vPosition.y - y); + if (v42 <= v16->uRadius) + { + v39 = abs(v16->vPosition.z - z); + if (v39 <= v16->uRadius) + { + v44 = int_get_vector_length(v17, v42, v39); + v24 = v16->uRadius; + if ((signed int)v44 < v24) + v6 += ((unsigned __int64)(30i64 * (signed int)(v44 << 16) / v24) >> 16) - 30; + } + } + } + } + } + } + + for (uint i = 0; i < pStationaryLightsStack->uNumLightsActive; ++i) + { + //StationaryLight* p = &pStationaryLightsStack->pLights[i]; + v26 = abs(pStationaryLightsStack->pLights[i].vPosition.x - x); + if (v26 <= pStationaryLightsStack->pLights[i].uRadius) + { + v40 = abs(pStationaryLightsStack->pLights[i].vPosition.y - y); + if (v40 <= pStationaryLightsStack->pLights[i].uRadius) + { + v37 = abs(pStationaryLightsStack->pLights[i].vPosition.z - z); + if (v37 <= pStationaryLightsStack->pLights[i].uRadius) + { + v45 = int_get_vector_length(v26, v40, v37); + //v33 = pStationaryLightsStack->pLights[i].uRadius; + if ((signed int)v45 < pStationaryLightsStack->pLights[i].uRadius) + v6 += ((unsigned __int64)(30i64 * (signed int)(v45 << 16) / pStationaryLightsStack->pLights[i].uRadius) >> 16) - 30; + } + } + } + } + + if (v6 <= 31) + { + if (v6 < 0) + v6 = 0; + } + else + v6 = 31; + return v6; +} + +//----- (0049D700) -------------------------------------------------------- +unsigned int __fastcall GetMaxMipLevels(unsigned int uDim) +{ + int v2; // ecx@1 + unsigned int v3; // eax@1 + + v2 = 0; + v3 = uDim - 1; + while (v3 & 1) + { + v3 >>= 1; + ++v2; + } + return v3 == 0 ? v2 : 0; +} + +//----- (0046E44E) -------------------------------------------------------- +int _46E44E_collide_against_faces_and_portals(unsigned int b1) +{ + BLVSector *pSector; // edi@1 + signed int v2; // ebx@1 + BLVFace *pFace; // esi@2 + __int16 pNextSector; // si@10 + int pArrayNum; // ecx@12 + unsigned __int8 v6; // sf@12 + unsigned __int8 v7; // of@12 + int result; // eax@14 + //int v10; // ecx@15 + int pFloor; // eax@16 + int v15; // eax@24 + int v16; // edx@25 + int v17; // eax@29 + unsigned int v18; // eax@33 + int v21; // eax@35 + int v22; // ecx@36 + int v23; // eax@40 + unsigned int v24; // eax@44 + int a3; // [sp+10h] [bp-48h]@28 + int v26; // [sp+14h] [bp-44h]@15 + int i; // [sp+18h] [bp-40h]@1 + int a10; // [sp+1Ch] [bp-3Ch]@1 + int v29; // [sp+20h] [bp-38h]@14 + int v32; // [sp+2Ch] [bp-2Ch]@15 + int pSectorsArray[10]; // [sp+30h] [bp-28h]@1 + + pSector = &pIndoor->pSectors[stru_721530.uSectorID]; + i = 1; + a10 = b1; + pSectorsArray[0] = stru_721530.uSectorID; + for (v2 = 0; v2 < pSector->uNumPortals; ++v2) + { + pFace = &pIndoor->pFaces[pSector->pPortals[v2]]; + if (stru_721530.sMaxX <= pFace->pBounding.x2 && stru_721530.sMinX >= pFace->pBounding.x1 + && stru_721530.sMaxY <= pFace->pBounding.y2 && stru_721530.sMinY >= pFace->pBounding.y1 + && stru_721530.sMaxZ <= pFace->pBounding.z2 && stru_721530.sMinZ >= pFace->pBounding.z1 + && abs((pFace->pFacePlane_old.dist + + stru_721530.normal.x * pFace->pFacePlane_old.vNormal.x + + stru_721530.normal.y * pFace->pFacePlane_old.vNormal.y + + stru_721530.normal.z * pFace->pFacePlane_old.vNormal.z) >> 16) <= stru_721530.field_6C + 16) + { + pNextSector = pFace->uSectorID == stru_721530.uSectorID ? pFace->uBackSectorID : pFace->uSectorID;//FrontSectorID + pArrayNum = i++; + v7 = i < 10; + v6 = i - 10 < 0; + pSectorsArray[pArrayNum] = pNextSector; + if (!(v6 ^ v7)) + break; + } + } + result = 0; + for (v29 = 0; v29 < i; v29++) + { + pSector = &pIndoor->pSectors[pSectorsArray[v29]]; + v32 = pSector->uNumFloors + pSector->uNumWalls + pSector->uNumCeilings; + for (v26 = 0; v26 < v32; v26++) + { + pFloor = pSector->pFloors[v26]; + pFace = &pIndoor->pFaces[pSector->pFloors[v26]]; + if (!pFace->Portal() + && stru_721530.sMaxX <= pFace->pBounding.x2 && stru_721530.sMinX >= pFace->pBounding.x1 + && stru_721530.sMaxY <= pFace->pBounding.y2 && stru_721530.sMinY >= pFace->pBounding.y1 + && stru_721530.sMaxZ <= pFace->pBounding.z2 && stru_721530.sMinZ >= pFace->pBounding.z1 + && pFloor != stru_721530.field_84) + { + v15 = (pFace->pFacePlane_old.dist + stru_721530.normal.x * pFace->pFacePlane_old.vNormal.x + + stru_721530.normal.y * pFace->pFacePlane_old.vNormal.y + + stru_721530.normal.z * pFace->pFacePlane_old.vNormal.z) >> 16; + if (v15 > 0) + { + v16 = (pFace->pFacePlane_old.dist + stru_721530.normal2.x * pFace->pFacePlane_old.vNormal.x + + stru_721530.normal2.y * pFace->pFacePlane_old.vNormal.y + + stru_721530.normal2.z * pFace->pFacePlane_old.vNormal.z) >> 16; + if (v15 <= stru_721530.prolly_normal_d || v16 <= stru_721530.prolly_normal_d) + { + if (v16 <= v15) + { + a3 = stru_721530.field_6C; + if (sub_47531C(stru_721530.prolly_normal_d, &a3, stru_721530.normal.x, stru_721530.normal.y, stru_721530.normal.z, + stru_721530.direction.x, stru_721530.direction.y, stru_721530.direction.z, pFace, a10)) + { + v17 = a3; + } + else + { + a3 = stru_721530.field_6C + stru_721530.prolly_normal_d; + if (!sub_475D85(&stru_721530.normal, &stru_721530.direction, &a3, pFace)) + goto LABEL_34; + v17 = a3 - stru_721530.prolly_normal_d; + a3 -= stru_721530.prolly_normal_d; + } + if (v17 < stru_721530.field_7C) + { + stru_721530.field_7C = v17; + v18 = 8 * pSector->pFloors[v26]; + LOBYTE(v18) = v18 | 6; + stru_721530.uFaceID = v18; + } + } + } + } + LABEL_34: + if (!(stru_721530.field_0 & 1) + || (v21 = (pFace->pFacePlane_old.dist + stru_721530.position.x * pFace->pFacePlane_old.vNormal.x + + stru_721530.position.y * pFace->pFacePlane_old.vNormal.y + + stru_721530.position.z * pFace->pFacePlane_old.vNormal.z) >> 16, v21 <= 0) + || (v22 = (pFace->pFacePlane_old.dist + stru_721530.field_4C * pFace->pFacePlane_old.vNormal.x + + stru_721530.field_50 * pFace->pFacePlane_old.vNormal.y + + stru_721530.field_54 * pFace->pFacePlane_old.vNormal.z) >> 16, v21 > stru_721530.prolly_normal_d) + && v22 > stru_721530.prolly_normal_d || v22 > v21) + continue; + a3 = stru_721530.field_6C; + if (sub_47531C(stru_721530.field_8_radius, &a3, stru_721530.position.x, stru_721530.position.y, stru_721530.position.z, + stru_721530.direction.x, stru_721530.direction.y, stru_721530.direction.z, pFace, a10)) + { + v23 = a3; + goto LABEL_43; + } + a3 = stru_721530.field_6C + stru_721530.field_8_radius; + if (sub_475D85(&stru_721530.position, &stru_721530.direction, &a3, pFace)) + { + v23 = a3 - stru_721530.prolly_normal_d; + a3 -= stru_721530.prolly_normal_d; + LABEL_43: + if (v23 < stru_721530.field_7C) + { + stru_721530.field_7C = v23; + v24 = 8 * pSector->pFloors[v26]; + LOBYTE(v24) = v24 | 6; + stru_721530.uFaceID = v24; + } + } + } + } + result = v29 + 1; + } + return result; +} +// 46E44E: using guessed type int var_28[10]; + +//----- (0046E889) -------------------------------------------------------- +int __fastcall _46E889_collide_against_bmodels(unsigned int ecx0) +{ + int result; // eax@1 + //int v3; // ebx@9 + int v8; // eax@19 + int v9; // ecx@20 + int v10; // eax@24 + unsigned int v14; // eax@28 + int v15; // eax@30 + int v16; // ecx@31 + unsigned int v17; // eax@36 + int v21; // eax@42 + unsigned int v22; // eax@43 + //int a11; // [sp+70h] [bp-18h]@1 + //int a10; // [sp+80h] [bp-8h]@1 + int a2; // [sp+84h] [bp-4h]@23 + + //a11 = ecx0; + + BLVFace face; // [sp+Ch] [bp-7Ch]@1 + + result = 0; + for (uint i = 0; i < (signed int)pOutdoor->uNumBModels; ++i) + { + if (stru_721530.sMaxX <= pOutdoor->pBModels[i].sMaxX && stru_721530.sMinX >= pOutdoor->pBModels[i].sMinX + && stru_721530.sMaxY <= pOutdoor->pBModels[i].sMaxY && stru_721530.sMinY >= pOutdoor->pBModels[i].sMinY + && stru_721530.sMaxZ <= pOutdoor->pBModels[i].sMaxZ && stru_721530.sMinZ >= pOutdoor->pBModels[i].sMinZ) + { + for (uint j = 0; j < pOutdoor->pBModels[i].uNumFaces; ++j) + { + if (stru_721530.sMaxX <= pOutdoor->pBModels[i].pFaces[j].pBoundingBox.x2 && stru_721530.sMinX >= pOutdoor->pBModels[i].pFaces[j].pBoundingBox.x1 + && stru_721530.sMaxY <= pOutdoor->pBModels[i].pFaces[j].pBoundingBox.y2 && stru_721530.sMinY >= pOutdoor->pBModels[i].pFaces[j].pBoundingBox.y1 + && stru_721530.sMaxZ <= pOutdoor->pBModels[i].pFaces[j].pBoundingBox.z2 && stru_721530.sMinZ >= pOutdoor->pBModels[i].pFaces[j].pBoundingBox.z1) + { + face.pFacePlane_old.vNormal.x = pOutdoor->pBModels[i].pFaces[j].pFacePlane.vNormal.x; + face.pFacePlane_old.vNormal.y = pOutdoor->pBModels[i].pFaces[j].pFacePlane.vNormal.y; + face.pFacePlane_old.vNormal.z = pOutdoor->pBModels[i].pFaces[j].pFacePlane.vNormal.z; + + face.pFacePlane_old.dist = pOutdoor->pBModels[i].pFaces[j].pFacePlane.dist; //incorrect + + face.uAttributes = pOutdoor->pBModels[i].pFaces[j].uAttributes; + + face.pBounding.x1 = pOutdoor->pBModels[i].pFaces[j].pBoundingBox.x1; + face.pBounding.y1 = pOutdoor->pBModels[i].pFaces[j].pBoundingBox.y1; + face.pBounding.z1 = pOutdoor->pBModels[i].pFaces[j].pBoundingBox.z1; + + face.pBounding.x2 = pOutdoor->pBModels[i].pFaces[j].pBoundingBox.x2; + face.pBounding.y2 = pOutdoor->pBModels[i].pFaces[j].pBoundingBox.y2; + face.pBounding.z2 = pOutdoor->pBModels[i].pFaces[j].pBoundingBox.z2; + + face.zCalc1 = pOutdoor->pBModels[i].pFaces[j].zCalc1; + face.zCalc2 = pOutdoor->pBModels[i].pFaces[j].zCalc2; + face.zCalc3 = pOutdoor->pBModels[i].pFaces[j].zCalc3; + + face.pXInterceptDisplacements = pOutdoor->pBModels[i].pFaces[j].pXInterceptDisplacements; + face.pYInterceptDisplacements = pOutdoor->pBModels[i].pFaces[j].pYInterceptDisplacements; + face.pZInterceptDisplacements = pOutdoor->pBModels[i].pFaces[j].pZInterceptDisplacements; + + face.uPolygonType = (PolygonType)pOutdoor->pBModels[i].pFaces[j].uPolygonType; + + face.uNumVertices = pOutdoor->pBModels[i].pFaces[j].uNumVertices; + + face.uBitmapID = pOutdoor->pBModels[i].pFaces[j].uTextureID; + + face.pVertexIDs = pOutdoor->pBModels[i].pFaces[j].pVertexIDs; + + if (!face.Ethereal() && !face.Portal()) + { + v8 = (face.pFacePlane_old.dist + face.pFacePlane_old.vNormal.x * stru_721530.normal.x + + face.pFacePlane_old.vNormal.y * stru_721530.normal.y + + face.pFacePlane_old.vNormal.z * stru_721530.normal.z) >> 16; + if (v8 > 0) + { + v9 = (face.pFacePlane_old.dist + face.pFacePlane_old.vNormal.x * stru_721530.normal2.x + + face.pFacePlane_old.vNormal.y * stru_721530.normal2.y + + face.pFacePlane_old.vNormal.z * stru_721530.normal2.z) >> 16; + if (v8 <= stru_721530.prolly_normal_d || v9 <= stru_721530.prolly_normal_d) + { + if (v9 <= v8) + { + a2 = stru_721530.field_6C; + if (sub_4754BF(stru_721530.prolly_normal_d, &a2, stru_721530.normal.x, stru_721530.normal.y, stru_721530.normal.z, + stru_721530.direction.x, stru_721530.direction.y, stru_721530.direction.z, &face, i, ecx0)) + { + v10 = a2; + } + else + { + a2 = stru_721530.prolly_normal_d + stru_721530.field_6C; + if (!sub_475F30(&a2, &face, stru_721530.normal.x, stru_721530.normal.y, stru_721530.normal.z, + stru_721530.direction.x, stru_721530.direction.y, stru_721530.direction.z, i)) + goto LABEL_29; + v10 = a2 - stru_721530.prolly_normal_d; + a2 -= stru_721530.prolly_normal_d; + } + if (v10 < stru_721530.field_7C) + { + stru_721530.field_7C = v10; + v14 = 8 * (j | (i << 6)); + LOBYTE(v14) = v14 | 6; + stru_721530.uFaceID = v14; + } + } + } + } + LABEL_29: + if (stru_721530.field_0 & 1) + { + v15 = (face.pFacePlane_old.dist + face.pFacePlane_old.vNormal.x * stru_721530.position.x + + face.pFacePlane_old.vNormal.y * stru_721530.position.y + + face.pFacePlane_old.vNormal.z * stru_721530.position.z) >> 16; + if (v15 > 0) + { + v16 = (face.pFacePlane_old.dist + face.pFacePlane_old.vNormal.x * stru_721530.field_4C + + face.pFacePlane_old.vNormal.y * stru_721530.field_50 + + face.pFacePlane_old.vNormal.z * stru_721530.field_54) >> 16; + if (v15 <= stru_721530.prolly_normal_d || v16 <= stru_721530.prolly_normal_d) + { + if (v16 <= v15) + { + a2 = stru_721530.field_6C; + if (sub_4754BF(stru_721530.field_8_radius, &a2, stru_721530.position.x, stru_721530.position.y, stru_721530.position.z, + stru_721530.direction.x, stru_721530.direction.y, stru_721530.direction.z, &face, i, ecx0)) + { + if (a2 < stru_721530.field_7C) + { + stru_721530.field_7C = a2; + v17 = 8 * (j | (i << 6)); + LOBYTE(v17) = v17 | 6; + stru_721530.uFaceID = v17; + } + } + else + { + a2 = stru_721530.field_6C + stru_721530.field_8_radius; + if (sub_475F30(&a2, &face, stru_721530.position.x, stru_721530.position.y, stru_721530.position.z, + stru_721530.direction.x, stru_721530.direction.y, stru_721530.direction.z, i)) + { + v21 = a2 - stru_721530.prolly_normal_d; + a2 -= stru_721530.prolly_normal_d; + if (a2 < stru_721530.field_7C) + { + stru_721530.field_7C = v21; + v22 = 8 * (j | (i << 6)); + LOBYTE(v22) = v22 | 6; + stru_721530.uFaceID = v22; + } + } + } + } + } + } + } + } + } + } + } + result = i; + } + return result; +} + +//----- (0046ED1B) -------------------------------------------------------- +int collide_against_floor(int x, int y, int z, unsigned int *pSectorID, unsigned int *pFaceID) +{ + uint uFaceID = -1; + int floor_level = BLV_GetFloorLevel(x, y, z, *pSectorID, &uFaceID); + + if (floor_level != -30000 && floor_level <= z + 50) + { + *pFaceID = uFaceID; + return floor_level; + } + + uint uSectorID = pIndoor->GetSector(x, y, z); + *pSectorID = uSectorID; + + floor_level = BLV_GetFloorLevel(x, y, z, uSectorID, &uFaceID); + if (uSectorID && floor_level != -30000) + *pFaceID = uFaceID; + else return -30000; + return floor_level; +} + +//----- (0046ED8A) -------------------------------------------------------- +void __fastcall _46ED8A_collide_against_sprite_objects(unsigned int _this) +{ + ObjectDesc *object; // edx@4 + int v10; // ecx@12 + int v11; // esi@13 + + for (uint i = 0; i < uNumSpriteObjects; ++i) + { + if (pSpriteObjects[i].uObjectDescID) + { + object = &pObjectList->pObjects[pSpriteObjects[i].uObjectDescID]; + if (!(object->uFlags & OBJECT_DESC_NO_COLLISION)) + { + if (stru_721530.sMaxX <= pSpriteObjects[i].vPosition.x + object->uRadius && stru_721530.sMinX >= pSpriteObjects[i].vPosition.x - object->uRadius + && stru_721530.sMaxY <= pSpriteObjects[i].vPosition.y + object->uRadius && stru_721530.sMinY >= pSpriteObjects[i].vPosition.y - object->uRadius + && stru_721530.sMaxZ <= pSpriteObjects[i].vPosition.z + object->uHeight && stru_721530.sMinZ >= pSpriteObjects[i].vPosition.z) + { + if (abs(((pSpriteObjects[i].vPosition.x - stru_721530.normal.x) * stru_721530.direction.y + - (pSpriteObjects[i].vPosition.y - stru_721530.normal.y) * stru_721530.direction.x) >> 16) + <= object->uHeight + stru_721530.prolly_normal_d) + { + v10 = ((pSpriteObjects[i].vPosition.x - stru_721530.normal.x) * stru_721530.direction.x + + (pSpriteObjects[i].vPosition.y - stru_721530.normal.y) * stru_721530.direction.y) >> 16; + if (v10 > 0) + { + v11 = stru_721530.normal.z + ((unsigned __int64)(stru_721530.direction.z * (signed __int64)v10) >> 16); + if (v11 >= pSpriteObjects[i].vPosition.z - stru_721530.prolly_normal_d) + { + if (v11 <= object->uHeight + stru_721530.prolly_normal_d + pSpriteObjects[i].vPosition.z) + { + if (v10 < stru_721530.field_7C) + sub_46DEF2(_this, i); + } + } + } + } + } + } + } + } +} + +//----- (0046EF01) -------------------------------------------------------- +int _46EF01_collision_chech_player(int a1) +{ + int result; // eax@1 + int v3; // ebx@7 + int v4; // esi@7 + int v5; // edi@8 + int v6; // ecx@9 + int v7; // edi@12 + int v10; // [sp+14h] [bp-8h]@7 + int v11; // [sp+18h] [bp-4h]@7 + + result = pParty->vPosition.x; + //v9 = pParty->uPartyHeight; + if (stru_721530.sMaxX <= pParty->vPosition.x + (2 * pParty->field_14_radius) && stru_721530.sMinX >= pParty->vPosition.x - (2 * pParty->field_14_radius) + && stru_721530.sMaxY <= pParty->vPosition.y + (2 * pParty->field_14_radius) && stru_721530.sMinY >= pParty->vPosition.y - (2 * pParty->field_14_radius) + && stru_721530.sMaxZ <= pParty->vPosition.z + pParty->uPartyHeight && stru_721530.sMinZ >= pParty->vPosition.z) + { + v3 = stru_721530.prolly_normal_d + (2 * pParty->field_14_radius); + v11 = pParty->vPosition.x - stru_721530.normal.x; + v4 = ((pParty->vPosition.x - stru_721530.normal.x) * stru_721530.direction.y + - (pParty->vPosition.y - stru_721530.normal.y) * stru_721530.direction.x) >> 16; + v10 = pParty->vPosition.y - stru_721530.normal.y; + result = abs(((pParty->vPosition.x - stru_721530.normal.x) * stru_721530.direction.y + - (pParty->vPosition.y - stru_721530.normal.y) * stru_721530.direction.x) >> 16); + if (result <= stru_721530.prolly_normal_d + (2 * pParty->field_14_radius)) + { + result = v10 * stru_721530.direction.y; + v5 = (v10 * stru_721530.direction.y + v11 * stru_721530.direction.x) >> 16; + if (v5 > 0) + { + v6 = fixpoint_mul(stru_721530.direction.z, v5) + stru_721530.normal.z; + result = pParty->vPosition.z; + if (v6 >= pParty->vPosition.z) + { + result = pParty->uPartyHeight + pParty->vPosition.z; + if (v6 <= (signed int)(pParty->uPartyHeight + pParty->vPosition.z) || a1) + { + result = integer_sqrt(v3 * v3 - v4 * v4); + v7 = v5 - integer_sqrt(v3 * v3 - v4 * v4); + if (v7 < 0) + v7 = 0; + if (v7 < stru_721530.field_7C) + { + stru_721530.field_7C = v7; + stru_721530.uFaceID = 4; + } + } + } + } + } + } + return result; +} + +//----- (0046E0B2) -------------------------------------------------------- +void _46E0B2_collide_against_decorations() +{ + BLVSector *sector; // ebp@1 + LevelDecoration *decor; // edi@2 + DecorationDesc *decor_desc; // esi@3 + int v8; // ebx@10 + int v9; // esi@11 + int v11; // eax@12 + int v12; // esi@14 + unsigned int v13; // eax@17 + signed int i; // [sp+4h] [bp-14h]@1 + int v15; // [sp+8h] [bp-10h]@10 + int v16; // [sp+Ch] [bp-Ch]@10 + int v17; // [sp+10h] [bp-8h]@10 + + sector = &pIndoor->pSectors[stru_721530.uSectorID]; + for (i = 0; i < sector->uNumDecorations; ++i) + { + decor = &pLevelDecorations[sector->pDecorationIDs[i]]; + if (!(decor->uFlags & LEVEL_DECORATION_INVISIBLE)) + { + decor_desc = &pDecorationList->pDecorations[decor->uDecorationDescID]; + if (!decor_desc->CanMoveThrough()) + { + if (stru_721530.sMaxX <= decor->vPosition.x + decor_desc->uRadius && stru_721530.sMinX >= decor->vPosition.x - decor_desc->uRadius + && stru_721530.sMaxY <= decor->vPosition.y + decor_desc->uRadius && stru_721530.sMinY >= decor->vPosition.y - decor_desc->uRadius + && stru_721530.sMaxZ <= decor->vPosition.z + decor_desc->uDecorationHeight && stru_721530.sMinZ >= decor->vPosition.z) + { + v16 = decor->vPosition.x - stru_721530.normal.x; + v15 = decor->vPosition.y - stru_721530.normal.y; + v8 = stru_721530.prolly_normal_d + decor_desc->uRadius; + v17 = ((decor->vPosition.x - stru_721530.normal.x) * stru_721530.direction.y + - (decor->vPosition.y - stru_721530.normal.y) * stru_721530.direction.x) >> 16; + if (abs(v17) <= stru_721530.prolly_normal_d + decor_desc->uRadius) + { + v9 = (v16 * stru_721530.direction.x + v15 * stru_721530.direction.y) >> 16; + if (v9 > 0) + { + v11 = stru_721530.normal.z + fixpoint_mul(stru_721530.direction.z, v9); + if (v11 >= decor->vPosition.z) + { + if (v11 <= decor_desc->uDecorationHeight + decor->vPosition.z) + { + v12 = v9 - integer_sqrt(v8 * v8 - v17 * v17); + if (v12 < 0) + v12 = 0; + if (v12 < stru_721530.field_7C) + { + stru_721530.field_7C = v12; + v13 = 8 * sector->pDecorationIDs[i]; + LOBYTE(v13) = v13 | 5; + stru_721530.uFaceID = v13; + } + } + } + } + } + } + } + } + } +} + +//----- (0046F04E) -------------------------------------------------------- +int _46F04E_collide_against_portals() +{ + unsigned int v1; // eax@1 + BLVFace *face; // eax@3 + int v4; // ecx@9 + int v5; // edx@9 + signed int result; // eax@21 + unsigned int v10; // [sp+8h] [bp-Ch]@1 + int a3; // [sp+Ch] [bp-8h]@13 + int v12; // [sp+10h] [bp-4h]@15 + + v1 = 0xFFFFFFu; + v10 = 0xFFFFFFu; + for (uint i = 0; i < pIndoor->pSectors[stru_721530.uSectorID].uNumPortals; ++i) + { + if (pIndoor->pSectors[stru_721530.uSectorID].pPortals[i] != stru_721530.field_80) + { + face = &pIndoor->pFaces[pIndoor->pSectors[stru_721530.uSectorID].pPortals[i]]; + if (stru_721530.sMaxX <= face->pBounding.x2 && stru_721530.sMinX >= face->pBounding.x1 + && stru_721530.sMaxY <= face->pBounding.y2 && stru_721530.sMinY >= face->pBounding.y1 + && stru_721530.sMaxZ <= face->pBounding.z2 && stru_721530.sMinZ >= face->pBounding.z1) + { + v4 = (stru_721530.normal.x * face->pFacePlane_old.vNormal.x + face->pFacePlane_old.dist + + stru_721530.normal.y * face->pFacePlane_old.vNormal.y + + stru_721530.normal.z * face->pFacePlane_old.vNormal.z) >> 16; + v5 = (stru_721530.normal2.z * face->pFacePlane_old.vNormal.z + face->pFacePlane_old.dist + + stru_721530.normal2.x * face->pFacePlane_old.vNormal.x + + stru_721530.normal2.y * face->pFacePlane_old.vNormal.y) >> 16; + if ((v4 < stru_721530.prolly_normal_d || v5 < stru_721530.prolly_normal_d) + && (v4 > -stru_721530.prolly_normal_d || v5 > -stru_721530.prolly_normal_d) + && (a3 = stru_721530.field_6C, sub_475D85(&stru_721530.normal, &stru_721530.direction, &a3, face)) + && a3 < (signed int)v10) + { + v10 = a3; + v12 = pIndoor->pSectors[stru_721530.uSectorID].pPortals[i]; + } + } + } + } + v1 = v10; + if (stru_721530.field_7C >= (signed int)v1 && (signed int)v1 <= stru_721530.field_6C) + { + stru_721530.field_80 = v12; + if (pIndoor->pFaces[v12].uSectorID == stru_721530.uSectorID) + stru_721530.uSectorID = pIndoor->pFaces[v12].uBackSectorID; + else + stru_721530.uSectorID = pIndoor->pFaces[v12].uSectorID; + stru_721530.field_7C = 268435455; + result = 0; + } + else + result = 1; + return result; +} + +//----- (0046DEF2) -------------------------------------------------------- +unsigned int __fastcall sub_46DEF2(signed int a2, unsigned int uLayingItemID) +{ + unsigned int result; // eax@1 + + result = uLayingItemID; + if (pObjectList->pObjects[pSpriteObjects[uLayingItemID].uObjectDescID].uFlags & 0x10) + result = _46BFFA_check_object_intercept(uLayingItemID, a2); + return result; +} + +//----- (0047253E) -------------------------------------------------------- +void UpdateObjects() +{ + ObjectDesc *object; // eax@5 + int v5; // ecx@6 + signed int v7; // eax@9 + signed int v11; // eax@17 + int v12; // edi@27 + int v18; // [sp+4h] [bp-10h]@27 + int v19; // [sp+8h] [bp-Ch]@27 + + for (uint i = 0; i < uNumSpriteObjects; ++i) + { + if (pSpriteObjects[i].uAttributes & OBJECT_40) + pSpriteObjects[i].uAttributes &= ~OBJECT_40; + else + { + object = &pObjectList->pObjects[pSpriteObjects[i].uObjectDescID]; + if (pSpriteObjects[i].AttachedToActor()) + { + v5 = PID_ID(pSpriteObjects[i].spell_target_pid); + pSpriteObjects[i].vPosition.x = pActors[v5].vPosition.x; + pSpriteObjects[i].vPosition.y = pActors[v5].vPosition.y; + pSpriteObjects[i].vPosition.z = pActors[v5].vPosition.z + pActors[v5].uActorHeight; + if (!pSpriteObjects[i].uObjectDescID) + continue; + pSpriteObjects[i].uSpriteFrameID += pEventTimer->uTimeElapsed; + if (!(object->uFlags & OBJECT_DESC_TEMPORARY)) + continue; + if (pSpriteObjects[i].uSpriteFrameID >= 0) + { + v7 = object->uLifetime; + if (pSpriteObjects[i].uAttributes & ITEM_BROKEN) + v7 = pSpriteObjects[i].field_20; + if (pSpriteObjects[i].uSpriteFrameID < v7) + continue; + } + SpriteObject::OnInteraction(i); + continue; + } + if (pSpriteObjects[i].uObjectDescID) + { + pSpriteObjects[i].uSpriteFrameID += pEventTimer->uTimeElapsed; + if (object->uFlags & OBJECT_DESC_TEMPORARY) + { + if (pSpriteObjects[i].uSpriteFrameID < 0) + { + SpriteObject::OnInteraction(i); + continue; + } + v11 = object->uLifetime; + if (pSpriteObjects[i].uAttributes & ITEM_BROKEN) + v11 = pSpriteObjects[i].field_20; + } + if (!(object->uFlags & OBJECT_DESC_TEMPORARY) || pSpriteObjects[i].uSpriteFrameID < v11) + { + if (uCurrentlyLoadedLevelType == LEVEL_Indoor) + SpriteObject::UpdateObject_fn0_BLV(i); + else + SpriteObject::UpdateObject_fn0_ODM(i); + if (pParty->bTurnBasedModeOn != 1 || !(pSpriteObjects[i].uSectorID & 4)) + continue; + v12 = abs(pParty->vPosition.x - pSpriteObjects[i].vPosition.x); + v18 = abs(pParty->vPosition.y - pSpriteObjects[i].vPosition.y); + v19 = abs(pParty->vPosition.z - pSpriteObjects[i].vPosition.z); + if (int_get_vector_length(v12, v18, v19) <= 5120) + continue; + SpriteObject::OnInteraction(i); + continue; + } + if (!(object->uFlags & OBJECT_DESC_INTERACTABLE)) + { + SpriteObject::OnInteraction(i); + continue; + } + _46BFFA_check_object_intercept(i, PID(OBJECT_Item, i)); + } + } + } +} + +//----- (0047531C) -------------------------------------------------------- +bool sub_47531C(int a1, int *a2, int pos_x, int pos_y, int pos_z, int dir_x, int dir_y, int dir_z, BLVFace *face, int a10) +{ + int v11; // ST1C_4@3 + int v12; // edi@3 + int v13; // esi@3 + int v14; // edi@4 + signed __int64 v15; // qtt@6 + //__int16 v16; // si@7 + int a7a; // [sp+30h] [bp+18h]@7 + int a9b; // [sp+38h] [bp+20h]@3 + int a9a; // [sp+38h] [bp+20h]@3 + int a10b; // [sp+3Ch] [bp+24h]@3 + signed int a10a; // [sp+3Ch] [bp+24h]@4 + int a10c; // [sp+3Ch] [bp+24h]@5 + + if (a10 && face->Ethereal()) + return 0; + v11 = fixpoint_mul(dir_x, face->pFacePlane_old.vNormal.x); + a10b = fixpoint_mul(dir_y, face->pFacePlane_old.vNormal.y); + a9b = fixpoint_mul(dir_z, face->pFacePlane_old.vNormal.z); + v12 = v11 + a9b + a10b; + a9a = v11 + a9b + a10b; + v13 = (a1 << 16) + - pos_x * face->pFacePlane_old.vNormal.x + - pos_y * face->pFacePlane_old.vNormal.y + - pos_z * face->pFacePlane_old.vNormal.z + - face->pFacePlane_old.dist; + if (abs((a1 << 16) + - pos_x * face->pFacePlane_old.vNormal.x + - pos_y * face->pFacePlane_old.vNormal.y + - pos_z * face->pFacePlane_old.vNormal.z - face->pFacePlane_old.dist) >= a1 << 16) + { + a10c = abs(v13) >> 14; + if (a10c > abs(v12)) + return 0; + LODWORD(v15) = v13 << 16; + HIDWORD(v15) = v13 >> 16; + v14 = a1; + a10a = v15 / a9a; + } + else + { + a10a = 0; + v14 = abs(v13) >> 16; + } + //v16 = pos_y + ((unsigned int)fixpoint_mul(a10a, dir_y) >> 16); + LOWORD(a7a) = (short)pos_x + ((unsigned int)fixpoint_mul(a10a, dir_x) >> 16) - fixpoint_mul(v14, face->pFacePlane_old.vNormal.x); + HIWORD(a7a) = pos_y + ((unsigned int)fixpoint_mul(a10a, dir_y) >> 16) - fixpoint_mul(v14, face->pFacePlane_old.vNormal.y); + if (!sub_475665(face, a7a, (short)pos_z + ((unsigned int)fixpoint_mul(a10a, dir_z) >> 16) - fixpoint_mul(v14, face->pFacePlane_old.vNormal.z))) + return 0; + *a2 = a10a >> 16; + if (a10a >> 16 < 0) + *a2 = 0; + return 1; +} + + +//----- (004754BF) -------------------------------------------------------- +bool sub_4754BF(int a1, int *a2, int X, int Y, int Z, int dir_x, int dir_y, int dir_z, BLVFace *face, int a10, int a11) +{ + int v12; // ST1C_4@3 + int v13; // edi@3 + int v14; // esi@3 + int v15; // edi@4 + signed __int64 v16; // qtt@6 + //__int16 v17; // si@7 + int a7a; // [sp+30h] [bp+18h]@7 + int a1b; // [sp+38h] [bp+20h]@3 + int a1a; // [sp+38h] [bp+20h]@3 + int a11b; // [sp+40h] [bp+28h]@3 + signed int a11a; // [sp+40h] [bp+28h]@4 + int a11c; // [sp+40h] [bp+28h]@5 + + if (a11 && face->Ethereal()) + return false; + v12 = fixpoint_mul(dir_x, face->pFacePlane_old.vNormal.x); + a11b = fixpoint_mul(dir_y, face->pFacePlane_old.vNormal.y); + a1b = fixpoint_mul(dir_z, face->pFacePlane_old.vNormal.z); + v13 = v12 + a1b + a11b; + a1a = v12 + a1b + a11b; + v14 = (a1 << 16) + - X * face->pFacePlane_old.vNormal.x + - Y * face->pFacePlane_old.vNormal.y + - Z * face->pFacePlane_old.vNormal.z + - face->pFacePlane_old.dist; + if (abs((a1 << 16) + - X * face->pFacePlane_old.vNormal.x + - Y * face->pFacePlane_old.vNormal.y + - Z * face->pFacePlane_old.vNormal.z - face->pFacePlane_old.dist) >= a1 << 16) + { + a11c = abs(v14) >> 14; + if (a11c > abs(v13)) + return false; + LODWORD(v16) = v14 << 16; + HIDWORD(v16) = v14 >> 16; + v15 = a1; + a11a = v16 / a1a; + } + else + { + a11a = 0; + v15 = abs(v14) >> 16; + } + //v17 = Y + ((unsigned int)fixpoint_mul(a11a, dir_y) >> 16); + LOWORD(a7a) = (short)X + ((unsigned int)fixpoint_mul(a11a, dir_x) >> 16) - fixpoint_mul(v15, face->pFacePlane_old.vNormal.x); + HIWORD(a7a) = Y + ((unsigned int)fixpoint_mul(a11a, dir_y) >> 16) - fixpoint_mul(v15, face->pFacePlane_old.vNormal.y); + if (!sub_4759C9(face, a10, a7a, (short)Z + ((unsigned int)fixpoint_mul(a11a, dir_z) >> 16) - fixpoint_mul(v15, face->pFacePlane_old.vNormal.z))) + return false; + *a2 = a11a >> 16; + if (a11a >> 16 < 0) + *a2 = 0; + return true; +} + +//----- (00475665) -------------------------------------------------------- +int sub_475665(BLVFace *face, int a2, __int16 a3) +{ + bool v16; // edi@14 + signed int v20; // ebx@18 + int v21; // edi@20 + signed int v22; // ST14_4@22 + signed __int64 v23; // qtt@22 + signed int result; // eax@25 + int v25; // [sp+14h] [bp-10h]@14 + int v26; // [sp+1Ch] [bp-8h]@2 + signed int v27; // [sp+20h] [bp-4h]@2 + signed int v28; // [sp+30h] [bp+Ch]@2 + signed int v29; // [sp+30h] [bp+Ch]@7 + signed int v30; // [sp+30h] [bp+Ch]@11 + signed int v31; // [sp+30h] [bp+Ch]@14 + + if (face->uAttributes & FACE_XY_PLANE) + { + v26 = (signed __int16)a2; + v27 = SHIWORD(a2); + if (face->uNumVertices) + { + for (v28 = 0; v28 < face->uNumVertices; v28++) + { + word_720C10_intercepts_xs[2 * v28] = face->pXInterceptDisplacements[v28] + pIndoor->pVertices[face->pVertexIDs[v28]].x; + word_720B40_intercepts_zs[2 * v28] = face->pYInterceptDisplacements[v28] + pIndoor->pVertices[face->pVertexIDs[v28]].y; + word_720C10_intercepts_xs[2 * v28 + 1] = face->pXInterceptDisplacements[v28 + 1] + pIndoor->pVertices[face->pVertexIDs[v28 + 1]].x; + word_720B40_intercepts_zs[2 * v28 + 1] = face->pYInterceptDisplacements[v28 + 1] + pIndoor->pVertices[face->pVertexIDs[v28 + 1]].y; + } + } + } + else + { + if (face->uAttributes & FACE_XZ_PLANE) + { + v26 = (signed __int16)a2; + v27 = a3; + if (face->uNumVertices) + { + for (v29 = 0; v29 < face->uNumVertices; v29++) + { + word_720C10_intercepts_xs[2 * v29] = face->pXInterceptDisplacements[v29] + pIndoor->pVertices[face->pVertexIDs[v29]].x; + word_720B40_intercepts_zs[2 * v29] = face->pZInterceptDisplacements[v29] + pIndoor->pVertices[face->pVertexIDs[v29]].z; + word_720C10_intercepts_xs[2 * v29 + 1] = face->pXInterceptDisplacements[v29 + 1] + pIndoor->pVertices[face->pVertexIDs[v29 + 1]].x; + word_720B40_intercepts_zs[2 * v29 + 1] = face->pZInterceptDisplacements[v29 + 1] + pIndoor->pVertices[face->pVertexIDs[v29 + 1]].z; + } + } + } + else + { + v26 = SHIWORD(a2); + v27 = a3; + if (face->uNumVertices) + { + for (v30 = 0; v30 < face->uNumVertices; v30++) + { + word_720C10_intercepts_xs[2 * v30] = face->pYInterceptDisplacements[v30] + pIndoor->pVertices[face->pVertexIDs[v30]].y; + word_720B40_intercepts_zs[2 * v30] = face->pZInterceptDisplacements[v30] + pIndoor->pVertices[face->pVertexIDs[v30]].z; + word_720C10_intercepts_xs[2 * v30 + 1] = face->pYInterceptDisplacements[v30 + 1] + pIndoor->pVertices[face->pVertexIDs[v30 + 1]].y; + word_720B40_intercepts_zs[2 * v30 + 1] = face->pZInterceptDisplacements[v30 + 1] + pIndoor->pVertices[face->pVertexIDs[v30 + 1]].z; + } + } + } + } + v31 = 0; + word_720C10_intercepts_xs[2 * face->uNumVertices] = word_720C10_intercepts_xs[0]; + word_720B40_intercepts_zs[2 * face->uNumVertices] = word_720B40_intercepts_zs[0]; + v16 = word_720B40_intercepts_zs[0] >= v27; + if (2 * face->uNumVertices <= 0) + return 0; + for (v25 = 0; v25 < 2 * face->uNumVertices; ++v25) + { + if (v31 >= 2) + break; + if (v16 ^ (word_720B40_intercepts_zs[v25 + 1] >= v27)) + { + if (word_720C10_intercepts_xs[v25 + 1] >= v26) + v20 = 0; + else + v20 = 2; + v21 = v20 | (word_720C10_intercepts_xs[v25] < v26); + if (v21 != 3) + { + v22 = word_720C10_intercepts_xs[v25 + 1] - word_720C10_intercepts_xs[v25]; + LODWORD(v23) = v22 << 16; + HIDWORD(v23) = v22 >> 16; + if (!v21 + || (word_720C10_intercepts_xs[v25] + ((signed int)(((unsigned __int64)(v23 + / (word_720B40_intercepts_zs[v25 + 1] - word_720B40_intercepts_zs[v25]) + * ((v27 - (signed int)word_720B40_intercepts_zs[v25]) << 16)) >> 16) + + 32768) >> 16) >= v26)) + ++v31; + } + } + v16 = word_720B40_intercepts_zs[v25 + 1] >= v27; + } + result = 1; + if (v31 != 1) + result = 0; + return result; +} + +//----- (004759C9) -------------------------------------------------------- +bool __fastcall sub_4759C9(BLVFace *face, int a2, int a3, __int16 a4) +{ + bool v12; // edi@14 + signed int v16; // ebx@18 + int v17; // edi@20 + signed int v18; // ST14_4@22 + signed __int64 v19; // qtt@22 + bool result; // eax@25 + int v21; // [sp+14h] [bp-10h]@14 + signed int v22; // [sp+18h] [bp-Ch]@1 + int v23; // [sp+1Ch] [bp-8h]@2 + signed int v24; // [sp+20h] [bp-4h]@2 + signed int a4d; // [sp+30h] [bp+Ch]@14 + + if (face->uAttributes & FACE_XY_PLANE) + { + v23 = (signed __int16)a3; + v24 = SHIWORD(a3); + if (face->uNumVertices) + { + for (v22 = 0; v22 < face->uNumVertices; ++v22) + { + word_720A70_intercepts_xs_plus_xs[2 * v22] = face->pXInterceptDisplacements[v22] + LOWORD(pOutdoor->pBModels[a2].pVertices.pVertices[face->pVertexIDs[v22]].x); + word_7209A0_intercepts_ys_plus_ys[2 * v22] = face->pYInterceptDisplacements[v22] + LOWORD(pOutdoor->pBModels[a2].pVertices.pVertices[face->pVertexIDs[v22]].y); + word_720A70_intercepts_xs_plus_xs[2 * v22 + 1] = face->pXInterceptDisplacements[v22 + 1] + LOWORD(pOutdoor->pBModels[a2].pVertices.pVertices[face->pVertexIDs[v22 + 1]].x); + word_7209A0_intercepts_ys_plus_ys[2 * v22 + 1] = face->pYInterceptDisplacements[v22 + 1] + LOWORD(pOutdoor->pBModels[a2].pVertices.pVertices[face->pVertexIDs[v22 + 1]].y); + } + } + } + else + { + if (face->uAttributes & FACE_XZ_PLANE) + { + v23 = (signed __int16)a3; + v24 = a4; + if (face->uNumVertices) + { + for (v22 = 0; v22 < face->uNumVertices; ++v22) + { + word_720A70_intercepts_xs_plus_xs[2 * v22] = face->pXInterceptDisplacements[v22] + LOWORD(pOutdoor->pBModels[a2].pVertices.pVertices[face->pVertexIDs[v22]].x); + word_7209A0_intercepts_ys_plus_ys[2 * v22] = face->pZInterceptDisplacements[v22] + LOWORD(pOutdoor->pBModels[a2].pVertices.pVertices[face->pVertexIDs[v22]].z); + word_720A70_intercepts_xs_plus_xs[2 * v22 + 1] = face->pXInterceptDisplacements[v22 + 1] + LOWORD(pOutdoor->pBModels[a2].pVertices.pVertices[face->pVertexIDs[v22 + 1]].x); + word_7209A0_intercepts_ys_plus_ys[2 * v22 + 1] = face->pZInterceptDisplacements[v22 + 1] + LOWORD(pOutdoor->pBModels[a2].pVertices.pVertices[face->pVertexIDs[v22 + 1]].z); + } + } + } + else + { + v23 = SHIWORD(a3); + v24 = a4; + if (face->uNumVertices) + { + for (v22 = 0; v22 < face->uNumVertices; ++v22) + { + word_720A70_intercepts_xs_plus_xs[2 * v22] = face->pYInterceptDisplacements[v22] + LOWORD(pOutdoor->pBModels[a2].pVertices.pVertices[face->pVertexIDs[v22]].y); + word_7209A0_intercepts_ys_plus_ys[2 * v22] = face->pZInterceptDisplacements[v22] + LOWORD(pOutdoor->pBModels[a2].pVertices.pVertices[face->pVertexIDs[v22]].z); + word_720A70_intercepts_xs_plus_xs[2 * v22 + 1] = face->pYInterceptDisplacements[v22 + 1] + LOWORD(pOutdoor->pBModels[a2].pVertices.pVertices[face->pVertexIDs[v22 + 1]].y); + word_7209A0_intercepts_ys_plus_ys[2 * v22 + 1] = face->pZInterceptDisplacements[v22 + 1] + LOWORD(pOutdoor->pBModels[a2].pVertices.pVertices[face->pVertexIDs[v22 + 1]].z); + } + } + } + } + a4d = 0; + word_720A70_intercepts_xs_plus_xs[2 * face->uNumVertices] = word_720A70_intercepts_xs_plus_xs[0]; + word_7209A0_intercepts_ys_plus_ys[2 * face->uNumVertices] = word_7209A0_intercepts_ys_plus_ys[0]; + v12 = word_7209A0_intercepts_ys_plus_ys[0] >= v24; + if (2 * face->uNumVertices <= 0) + return 0; + for (v21 = 0; v21 < 2 * face->uNumVertices; ++v21) + { + if (a4d >= 2) + break; + if (v12 ^ (word_7209A0_intercepts_ys_plus_ys[v21 + 1] >= v24)) + { + if (word_720A70_intercepts_xs_plus_xs[v21 + 1] >= v23) + v16 = 0; + else + v16 = 2; + v17 = v16 | (word_720A70_intercepts_xs_plus_xs[v21] < v23); + if (v17 != 3) + { + v18 = word_720A70_intercepts_xs_plus_xs[v21 + 1] - word_720A70_intercepts_xs_plus_xs[v21]; + LODWORD(v19) = v18 << 16; + HIDWORD(v19) = v18 >> 16; + if (!v17 + || (word_720A70_intercepts_xs_plus_xs[v21] + ((signed int)(((unsigned __int64)(v19 + / (word_7209A0_intercepts_ys_plus_ys[v21 + 1] - word_7209A0_intercepts_ys_plus_ys[v21]) + * ((v24 - (signed int)word_7209A0_intercepts_ys_plus_ys[v21]) << 16)) >> 16) + + 0x8000) >> 16) >= v23)) + ++a4d; + } + } + v12 = word_7209A0_intercepts_ys_plus_ys[v21 + 1] >= v24; + } + result = 1; + if (a4d != 1) + result = 0; + return result; +} + +//----- (00475D85) -------------------------------------------------------- +bool __fastcall sub_475D85(Vec3_int_ *a1, Vec3_int_ *a2, int *a3, BLVFace *a4) +{ + BLVFace *v4; // ebx@1 + int v5; // ST24_4@2 + int v6; // ST28_4@2 + int v7; // edi@2 + int v8; // eax@5 + signed int v9; // esi@5 + signed __int64 v10; // qtt@10 + Vec3_int_ *v11; // esi@11 + int v12; // ST14_4@11 + Vec3_int_ *v14; // [sp+Ch] [bp-18h]@1 + Vec3_int_ *v15; // [sp+14h] [bp-10h]@1 + // int v16; // [sp+18h] [bp-Ch]@2 + int v17; // [sp+20h] [bp-4h]@10 + int a4b; // [sp+30h] [bp+Ch]@2 + int a4c; // [sp+30h] [bp+Ch]@9 + signed int a4a; // [sp+30h] [bp+Ch]@10 + + v4 = a4; + v15 = a2; + v14 = a1; + v5 = fixpoint_mul(a2->x, a4->pFacePlane_old.vNormal.x); + a4b = fixpoint_mul(a2->y, a4->pFacePlane_old.vNormal.y); + v6 = fixpoint_mul(a2->z, v4->pFacePlane_old.vNormal.z); + v7 = v5 + v6 + a4b; + //(v16 = v5 + v6 + a4b) == 0; + if (a4->uAttributes & 0x20000000 || !v7 || v7 > 0 && !v4->Portal()) + return 0; + v8 = v4->pFacePlane_old.vNormal.z * a1->z; + v9 = -(v4->pFacePlane_old.dist + v8 + a1->y * v4->pFacePlane_old.vNormal.y + a1->x * v4->pFacePlane_old.vNormal.x); + if (v7 <= 0) + { + if (v4->pFacePlane_old.dist + v8 + a1->y * v4->pFacePlane_old.vNormal.y + a1->x * v4->pFacePlane_old.vNormal.x < 0) + return 0; + } + else + { + if (v9 < 0) + return 0; + } + a4c = abs(-(v4->pFacePlane_old.dist + v8 + a1->y * v4->pFacePlane_old.vNormal.y + a1->x * v4->pFacePlane_old.vNormal.x)) >> 14; + v11 = v14; + LODWORD(v10) = v9 << 16; + HIDWORD(v10) = v9 >> 16; + a4a = v10 / v7; + v17 = v10 / v7; + LOWORD(v12) = LOWORD(v14->x) + (((unsigned int)fixpoint_mul(v17, v15->x) + 0x8000) >> 16); + HIWORD(v12) = LOWORD(v11->y) + (((unsigned int)fixpoint_mul(v17, v15->y) + 0x8000) >> 16); + if (a4c > abs(v7) || (v17 > *a3 << 16) || !sub_475665(v4, v12, LOWORD(v11->z) + (((unsigned int)fixpoint_mul(v17, v15->z) + 0x8000) >> 16))) + return 0; + *a3 = a4a >> 16; + return 1; +} + +//----- (00475F30) -------------------------------------------------------- +bool __fastcall sub_475F30(int *a1, BLVFace *a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9) +{ + int v10; // ST20_4@2 + int v11; // ST28_4@2 + int v12; // ST24_4@2 + int v13; // zf@2 + int v14; // edi@2 + signed int v16; // esi@5 + int v17; // ST20_4@9 + signed __int64 v18; // qtt@10 + int v19; // ST14_4@11 + int v22; // [sp+1Ch] [bp-8h]@2 + int v23; // [sp+1Ch] [bp-8h]@10 + signed int v24; // [sp+20h] [bp-4h]@10 + + v10 = fixpoint_mul(a6, a2->pFacePlane_old.vNormal.x); + v11 = fixpoint_mul(a7, a2->pFacePlane_old.vNormal.y); + v12 = fixpoint_mul(a8, a2->pFacePlane_old.vNormal.z); + v13 = v10 + v12 + v11; + v14 = v10 + v12 + v11; + v22 = v10 + v12 + v11; + if (a2->Ethereal() || !v13 || v14 > 0 && !a2->Portal()) + return 0; + v16 = -(a2->pFacePlane_old.dist + a4 * a2->pFacePlane_old.vNormal.y + a3 * a2->pFacePlane_old.vNormal.x + a5 * a2->pFacePlane_old.vNormal.z); + if (v14 <= 0) + { + if (a2->pFacePlane_old.dist + a4 * a2->pFacePlane_old.vNormal.y + a3 * a2->pFacePlane_old.vNormal.x + a5 * a2->pFacePlane_old.vNormal.z < 0) + return 0; + } + else + { + if (v16 < 0) + return 0; + } + v17 = abs(-(a2->pFacePlane_old.dist + a4 * a2->pFacePlane_old.vNormal.y + a3 * a2->pFacePlane_old.vNormal.x + a5 * a2->pFacePlane_old.vNormal.z)) >> 14; + LODWORD(v18) = v16 << 16; + HIDWORD(v18) = v16 >> 16; + v24 = v18 / v22; + v23 = v18 / v22; + LOWORD(v19) = a3 + (((unsigned int)fixpoint_mul(v23, a6) + 0x8000) >> 16); + HIWORD(v19) = a4 + (((unsigned int)fixpoint_mul(v23, a7) + 0x8000) >> 16); + if (v17 > abs(v14) || v23 > *a1 << 16 || !sub_4759C9(a2, a9, v19, a5 + (((unsigned int)fixpoint_mul(v23, a8) + 0x8000) >> 16))) + return 0; + *a1 = v24 >> 16; + return 1; +} + +//----- (00479089) -------------------------------------------------------- +bool __fastcall IsBModelVisible(unsigned int uModelID, int *reachable) +{ + int v3; // edi@1 + int v4; // ebx@1 + int v9; // eax@3 + signed int v11; // esi@6 + int v12; // esi@8 + bool result; // eax@9 + int v17; // [sp+1Ch] [bp-10h]@1 + int v19; // [sp+20h] [bp-Ch]@3 + int angle; // [sp+24h] [bp-8h]@1 + + angle = (signed int)(pODMRenderParams->uCameraFovInDegrees << 11) / 360 / 2; + v3 = pOutdoor->pBModels[uModelID].vBoundingCenter.x - pGame->pIndoorCameraD3D->vPartyPos.x; + v4 = pOutdoor->pBModels[uModelID].vBoundingCenter.y - pGame->pIndoorCameraD3D->vPartyPos.y; + stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationX); + v17 = v3 * stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationY) + v4 * stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationY); + if (pGame->pIndoorCameraD3D->sRotationX) + v17 = fixpoint_mul(v17, stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationX)); + v19 = v4 * stru_5C6E00->Cos(pGame->pIndoorCameraD3D->sRotationY) - v3 * stru_5C6E00->Sin(pGame->pIndoorCameraD3D->sRotationY); + v9 = int_get_vector_length(abs(v3), abs(v4), 0); + //v10 = v14 * 188; + //v22 = v9; + *reachable = false; + if (v9 < pOutdoor->pBModels[uModelID].sBoundingRadius + 256) + *reachable = true; + if (v19 >= 0) + v11 = fixpoint_mul(stru_5C6E00->Sin(angle), v17) - fixpoint_mul(stru_5C6E00->Cos(angle), v19); + else + v11 = fixpoint_mul(stru_5C6E00->Cos(angle), v19) + fixpoint_mul(stru_5C6E00->Sin(angle), v17); + v12 = v11 >> 16; + if (v9 <= pODMRenderParams->shading_dist_mist + 2048) + { + //if ( abs(v12) > *(int *)((char *)&pOutdoor->pBModels->sBoundingRadius + v10) + 512 ) + if (abs(v12) > pOutdoor->pBModels[uModelID].sBoundingRadius + 512) + { + result = v12 < 0; + LOBYTE(result) = v12 >= 0; + return result; + } + else + return true; + } + return false; +} + +//----- (00479295) -------------------------------------------------------- +int Polygon::_479295() +{ + int v3; // ecx@4 + int v4; // eax@4 + int v5; // edx@4 + // int v6; // ST14_4@5 + Vec3_int_ thisa; // [sp+Ch] [bp-10h]@8 + int v11; // [sp+18h] [bp-4h]@4 + + if (!this->pODMFace->pFacePlane.vNormal.z) + { + v3 = this->pODMFace->pFacePlane.vNormal.x; + v4 = -this->pODMFace->pFacePlane.vNormal.y; + v5 = 0; + v11 = 65536; + } + else if ((this->pODMFace->pFacePlane.vNormal.x || this->pODMFace->pFacePlane.vNormal.y) + && abs(this->pODMFace->pFacePlane.vNormal.z) < 59082) + { + thisa.x = -this->pODMFace->pFacePlane.vNormal.y; + thisa.y = this->pODMFace->pFacePlane.vNormal.x; + thisa.z = 0; + thisa.Normalize_float(); + v4 = thisa.x; + v3 = thisa.y; + v5 = 0; + v11 = 65536; + } + else + { + v3 = 0; + v4 = 65536; + v11 = 0; + v5 = -65536; + } + sTextureDeltaU = this->pODMFace->sTextureDeltaU; + sTextureDeltaV = this->pODMFace->sTextureDeltaV; + ptr_38->_48616B_frustum_odm(v4, v3, 0, 0, v5, v11); + return 1; +} + + +unsigned short *LoadTgaTexture(const wchar_t *filename, int *out_width = nullptr, int *out_height = nullptr) +{ +#pragma pack(push, 1) + struct TGAHeader + { + unsigned char tgaSkip; + unsigned char colourmaptype; // type of colour map 0=none, 1=has palette + unsigned char tgaType; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed + + short colourmapstart; // first colour map entry in palette + short colourmaplength; // number of colours in palette + char colourmapbits; // number of bits per palette entry 15,16,24,32 + + //unsigned char tgaDontCare2[9]; + short xstart; // image x origin + short ystart; // image y origin + + unsigned short tgaWidth; + unsigned short tgaHeight; + unsigned char tgaBPP; + + char descriptor; // image descriptor bits: 00vhaaaa + // h horizontal flip + // v vertical flip + // a alpha bits + }; +#pragma pack(pop) + + if (out_width) + *out_width = 0; + if (out_height) + *out_height = 0; + + DWORD w; + void* file = CreateFileW(filename, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr); + if (file == INVALID_HANDLE_VALUE) + return nullptr; + + TGAHeader header; + ReadFile(file, &header, sizeof(header), &w, nullptr); + SetFilePointer(file, header.tgaSkip, nullptr, FILE_CURRENT); + + if (header.tgaBPP != 24 || header.tgaType != 2) + { + CloseHandle(file); + return nullptr; + } + + int imgSize = header.tgaWidth * header.tgaHeight * 3; + unsigned char* pixels = new unsigned char[imgSize]; + ReadFile(file, pixels, imgSize, &w, nullptr); + CloseHandle(file); + + if (w != imgSize) + { + delete[] pixels; + return nullptr; + } + + if (out_width) + *out_width = header.tgaWidth; + if (out_height) + *out_height = header.tgaHeight; + + unsigned short* pixels_16bit = new unsigned short[imgSize / 3]; + for (int i = 0; i < imgSize / 3; ++i) + { + pixels_16bit[i] = (pixels[i * 3] / 8 & 0x1F) | + ((pixels[i * 3 + 1] / 4 & 0x3F) << 5) | + ((pixels[i * 3 + 2] / 8 & 0x1F) << 11); + } + delete[] pixels; + return pixels_16bit; +} + +unsigned short *skybox_xn, *skybox_xp, +*skybox_yn, *skybox_yp, +*skybox_zn, *skybox_zp; +int skybox_width, skybox_height; + +IDirect3DTexture2 *skybox_texture; +IDirectDrawSurface4 *skybox_surface; + +bool Skybox_Initialize(const wchar_t *skybox_name) +{ + wchar_t xn_filename[1024], xp_filename[1024], + yn_filename[1024], yp_filename[1024], + zn_filename[1024], zp_filename[1024]; + swprintf(xn_filename, wcslen(L"%s_xn.tga"), L"%s_xn.tga", skybox_name); swprintf(xp_filename, wcslen(L"%s_xp.tga"), L"%s_xp.tga", skybox_name); + swprintf(yn_filename, wcslen(L"%s_yn.tga"), L"%s_yn.tga", skybox_name); swprintf(yp_filename, wcslen(L"%s_yp.tga"), L"%s_yp.tga", skybox_name); + swprintf(zn_filename, wcslen(L"%s_zn.tga"), L"%s_zn.tga", skybox_name); swprintf(zp_filename, wcslen(L"%s_zp.tga"), L"%s_zp.tga", skybox_name); + + int xn_width, xn_height; + skybox_xn = LoadTgaTexture(xn_filename, &xn_width, &xn_height); + if (!skybox_xn) + return false; + + int xp_width, xp_height; + skybox_xp = LoadTgaTexture(xp_filename, &xp_width, &xp_height); + if (!skybox_xp || xp_width != xn_width || xp_height != xn_height) + { + delete[] skybox_xn; + delete[] skybox_xp; + return false; + } + + int yn_width, yn_height; + skybox_yn = LoadTgaTexture(yn_filename, &yn_width, &yn_height); + if (!skybox_yn || yn_width != xn_width || yn_height != xn_height) + { + delete[] skybox_xn; + delete[] skybox_xp; + delete[] skybox_yn; + return false; + } + + int yp_width, yp_height; + skybox_yp = LoadTgaTexture(yp_filename, &yp_width, &yp_height); + if (!skybox_yp || yp_width != xn_width || yp_height != xn_height) + { + delete[] skybox_xn; + delete[] skybox_xp; + delete[] skybox_yn; + delete[] skybox_yp; + return false; + } + + int zn_width, zn_height; + skybox_zn = LoadTgaTexture(zn_filename, &zn_width, &zn_height); + if (!skybox_zn || zn_width != xn_width || zn_height != xn_height) + { + delete[] skybox_xn; + delete[] skybox_xp; + delete[] skybox_yn; + delete[] skybox_yp; + delete[] skybox_zn; + return false; + } + + int zp_width, zp_height; + skybox_zp = LoadTgaTexture(zp_filename, &zp_width, &zp_height); + if (!skybox_zp || zp_width != xn_width || zp_height != xn_height) + { + delete[] skybox_xn; + delete[] skybox_xp; + delete[] skybox_yn; + delete[] skybox_yp; + delete[] skybox_zn; + delete[] skybox_zp; + return false; + } + + skybox_width = xn_width; + skybox_height = xn_height; + + __debugbreak(); + //if (!pRenderer->pRenderD3D->CreateTexture(skybox_width, skybox_height, &skybox_surface, &skybox_texture, + //false, false, pRenderer->uMinDeviceTextureDim)) + return false; + + return true; +} + +struct vector +{ + float x, y, z; +}; + +struct matrix +{ + float m[4][4]; +}; + +void VectorNormalize(vector *v) +{ + float invmag = 1.0f / sqrtf(v->x * v->x + v->y * v->y + v->z * v->z); + v->x *= invmag; + v->y *= invmag; + v->z *= invmag; +} + +void MatrixRotationAxis(matrix *pout, CONST vector *pv, float angle) +{ + memset(pout, 0, sizeof(matrix)); + pout->m[3][0] = 0; + pout->m[3][1] = 0; + pout->m[3][2] = 0; + pout->m[3][3] = 1; + + vector v; + v.x = pv->x; v.y = pv->y; v.z = pv->z; + VectorNormalize(&v); + + pout->m[0][0] = (1.0f - cos(angle)) * v.x * v.x + cos(angle); + pout->m[1][0] = (1.0f - cos(angle)) * v.x * v.y - sin(angle) * v.z; + pout->m[2][0] = (1.0f - cos(angle)) * v.x * v.z + sin(angle) * v.y; + pout->m[0][1] = (1.0f - cos(angle)) * v.y * v.x + sin(angle) * v.z; + pout->m[1][1] = (1.0f - cos(angle)) * v.y * v.y + cos(angle); + pout->m[2][1] = (1.0f - cos(angle)) * v.y * v.z - sin(angle) * v.x; + pout->m[0][2] = (1.0f - cos(angle)) * v.z * v.x - sin(angle) * v.y; + pout->m[1][2] = (1.0f - cos(angle)) * v.z * v.y + sin(angle) * v.x; + pout->m[2][2] = (1.0f - cos(angle)) * v.z * v.z + cos(angle); +} + +void VectorTransform(const matrix *m, const vector *v, vector *out) +{ + out->x = m->m[0][0] * v->x + m->m[1][0] * v->y + m->m[2][0] * v->z + m->m[3][0]; + out->y = m->m[0][1] * v->x + m->m[1][1] * v->y + m->m[2][1] * v->z + m->m[3][1]; + out->z = m->m[0][2] * v->x + m->m[1][2] * v->y + m->m[2][2] * v->z + m->m[3][2]; +} + +bool DrawSkyD3D_Skybox() +{ + static bool initialized = false, + initialization_failed = false; + if (initialization_failed) + return false; + + static int last_camera_rot_y, + last_camera_rot_x; + if (!initialized) + { + if (!Skybox_Initialize(L"data/skybox/stars")) + { + initialization_failed = true; + return false; + } + initialized = true; + + last_camera_rot_y = pParty->sRotationY + 1; // force update for the first run + last_camera_rot_x = pParty->sRotationX + 1; + } + + /* + r(y) = + cos y 0 sin y 0 + 0 1 0 0 + -sin y 0 cos y 0 + 0 0 0 1 + + x cos y - z sin y + y + x sin y + z cos y + 1 + + + + r(x) = // should be r(right) actually + 1 0 0 0 + 0 cos x -sin x 0 + 0 sin x cos x 0 + 0 0 0 1 + + + x + y cos x + z sin x + -y sin x + z cos x + 1 + + */ + + if (last_camera_rot_y == pParty->sRotationY && + last_camera_rot_x == pParty->sRotationX) + { + draw: + struct RenderVertexD3D3 v[6]; + + v[0].pos.x = pViewport->uScreen_TL_X; + v[0].pos.y = pViewport->uScreen_TL_Y; + v[0].pos.z = 0.99989998; + v[0].rhw = 1; + v[0].diffuse = -1; + v[0].specular = 0; + v[0].texcoord.x = 0; + v[0].texcoord.y = 0; + + v[1].pos.x = pViewport->uScreen_TL_X + pViewport->uScreenWidth; + v[1].pos.y = pViewport->uScreen_TL_Y + pViewport->uScreenHeight; + v[1].pos.z = 0.99989998; + v[1].rhw = 1; + v[1].diffuse = -1; + v[1].specular = 0; + v[1].texcoord.x = (float)pViewport->uScreenWidth / skybox_width; + v[1].texcoord.y = (float)pViewport->uScreenHeight / skybox_height; + + v[2].pos.x = pViewport->uScreen_TL_X + pViewport->uScreenWidth; + v[2].pos.y = pViewport->uScreen_TL_Y; + v[2].pos.z = 0.99989998; + v[2].rhw = 1; + v[2].diffuse = -1; + v[2].specular = 0; + v[2].texcoord.x = (float)pViewport->uScreenWidth / skybox_width; + v[2].texcoord.y = 0; + + memcpy(&v[3], &v[0], sizeof(*v)); + + v[4].pos.x = pViewport->uScreen_TL_X; + v[4].pos.y = pViewport->uScreen_TL_Y + pViewport->uScreenHeight; + v[4].pos.z = 0.99989998; + v[4].rhw = 1; + v[4].diffuse = -1; + v[4].specular = 0; + v[4].texcoord.x = 0; + v[4].texcoord.y = (float)pViewport->uScreenHeight / skybox_height; + + memcpy(&v[5], &v[1], sizeof(*v)); + + __debugbreak(); + /* + pRenderer->pRenderD3D->pDevice->SetRenderState(D3DRENDERSTATE_CULLMODE, D3DCULL_NONE); + pRenderer->pRenderD3D->pDevice->SetTexture(0, skybox_texture); + pRenderer->pRenderD3D->pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1, v, 6, D3DDP_DONOTUPDATEEXTENTS | D3DDP_DONOTLIGHT); + */ + return true; + } + + + DDSURFACEDESC2 desc; + desc.dwSize = sizeof(desc); + if (!pRenderer->LockSurface_DDraw4(skybox_surface, &desc, DDLOCK_WAIT | DDLOCK_WRITEONLY)) + return false; + + last_camera_rot_y = pParty->sRotationY; + last_camera_rot_x = pParty->sRotationX; + + float aspect = (float)pViewport->uScreenWidth / (float)pViewport->uScreenHeight; + float fov_x = 3.141592f * (pODMRenderParams->uCameraFovInDegrees + 0) / 360.0f; + float fov_y = fov_x / aspect; + + float ray_dx = fov_x / (float)pViewport->uScreenWidth, + ray_dy = fov_y / (float)pViewport->uScreenHeight; + float party_angle_x = 2 * 3.141592653589 * pParty->sRotationX / 2048.0, + party_angle_y = 2 * 3.141592653589 * pParty->sRotationY / 2048.0; + for (int y = 0; y < pViewport->uScreenHeight; ++y) + for (int x = 0; x < pViewport->uScreenWidth; ++x) + { + float angle_x = party_angle_x - (y - pViewport->uScreenHeight / 2) * ray_dy; + float angle_y = party_angle_y - (x - pViewport->uScreenWidth / 2) * ray_dx; + + float _dir_x_ = 1, + _dir_y_ = 0, + _dir_z_ = 0; + + float dir_x_ = _dir_x_ * cosf(angle_y);// - _dir_z_ * sinf(angle_y); // rotation around y + //float dir_y_ = _dir_y_; + float dir_z_ = _dir_x_ * sinf(angle_y);// + _dir_z_ * cosf(angle_y); + + //float dir_x = dir_x_; // rotation around x + //float dir_y = /*dir_y_ * cosf(angle_x)*/ + dir_z_ * sinf(angle_x); + //float dir_z = /*-dir_y_ * sinf(angle_x)*/ + dir_z_ * cosf(angle_x); + + vector right; // rotate around right actually to avoid space distortion + right.x = /*dir_y * 0*/ -dir_z_ * 1; + right.y = /*dir_z_ * 0 - dir_x_ * */0; + right.z = dir_x_ * 1/* - dir_y_ * 0*/; + //VectorNormalize(&right); + + matrix rightMatrix; + MatrixRotationAxis(&rightMatrix, &right, angle_x); + + vector v1, v2; + v1.x = dir_x_; v1.y = 0; v1.z = dir_z_; + VectorTransform(&rightMatrix, &v1, &v2); + + float dir_x = v2.x, + dir_y = v2.y, + dir_z = v2.z; + + float abs_dir_x = fabsf(dir_x), + abs_dir_y = fabsf(dir_y), + abs_dir_z = fabsf(dir_z); + + unsigned short color = (0x1F << 11) | (0x1F << 5) | (5); //default to orange + if (abs_dir_x >= abs_dir_y) + { + if (abs_dir_x >= abs_dir_z) + { + if (dir_x >= 0) + { + float instersect_y = dir_y / (2.0f * dir_x); // plane equation for this side is x + 0.5 = 0 + float instersect_z = dir_z / (2.0f * dir_x); + + float u = 1.0f - (instersect_z + 0.5f), + v = 1.0f - (instersect_y + 0.5f); + + int tx = u * (skybox_width - 1), + ty = v * (skybox_height - 1); + + color = skybox_xp[ty * skybox_width + tx]; + //color = ty * 0x1F / skybox_height; + } + else + { + float instersect_y = dir_y / (2.0f * dir_x); + float instersect_z = dir_z / (2.0f * dir_x); + + float u = 1.0f - (instersect_z + 0.5f), + v = instersect_y + 0.5f; + + int tx = u * (skybox_width - 1), + ty = v * (skybox_height - 1); + + color = skybox_xn[ty * skybox_width + tx]; + //color = tx * 0x1F / skybox_height; + } + } + else if (dir_z >= 0) + goto DIR_ZP; + else + goto DIR_ZN; + } + else if (abs_dir_y >= abs_dir_z) + { + if (dir_y >= 0) + { + float instersect_x = dir_x / (2.0f * dir_y); + float instersect_z = dir_z / (2.0f * dir_y); + + float u = instersect_x + 0.5f, + v = instersect_z + 0.5f; + + int tx = u * (skybox_width - 1), + ty = v * (skybox_height - 1); + + color = skybox_yp[ty * skybox_width + tx]; + //color = tx * 0x1F / skybox_height; + } + /*else should never be seen i guess + { + __debugbreak(); + // -y + //Log::Warning(L"(%03u, %03u): -y", x, y); + }*/ + } + else if (dir_z >= 0) + { + DIR_ZP: + // +z + float instersect_x = dir_x / (2.0f * dir_z); + float instersect_y = dir_y / (2.0f * dir_z); + //float intersect_z = 0.5f; + + float u = instersect_x + 0.5f, + v = -instersect_y + 0.5f; + + int tx = u * (skybox_width - 1), + ty = v * (skybox_height - 1); + + color = skybox_zp[ty * skybox_width + tx]; + } + else + { + DIR_ZN: + // -z + float instersect_x = -dir_x / (2.0f * dir_z); + float instersect_y = -dir_y / (2.0f * dir_z); + //float intersect_z = -0.5f; + + float u = 1.0f - instersect_x - 0.5f, + v = -instersect_y + 0.5f; + + int tx = u * (skybox_width - 1), + ty = v * (skybox_height - 1); + + color = skybox_zn[ty * skybox_width + tx]; + } + + //pRenderer->pTargetSurface[(pViewport->uScreenY + y) * pRenderer->uTargetSurfacePitch + pViewport->uScreenX + x] = color; + ((unsigned __int16 *)((char *)desc.lpSurface + y * desc.lPitch))[x] = color; + } + + ErrD3D((skybox_surface)->Unlock(0)); + goto draw; +} + +//----- (00485F53) -------------------------------------------------------- +void sr_485F53(Vec2_int_ *v) +{ + ++v->y; + if (v->y > 1000) + v->y = 0; +} + +//----- (0048607B) -------------------------------------------------------- +void Polygon::Create_48607B(stru149 *a2) +{ + this->pTexture = 0; + this->ptr_38 = a2; +} + +//----- (00486089) -------------------------------------------------------- +void Polygon::_normalize_v_18() +{ + //double v2; // st7@1 + //double v3; // st6@1 + //double v5; // st5@1 + + // v2 = (double)this->v_18.x; + //v3 = (double)this->v_18.y; + // v5 = (double)this->v_18.z; + float len = sqrt((double)this->v_18.z * (double)this->v_18.z + (double)this->v_18.y * (double)this->v_18.y + (double)this->v_18.x * (double)this->v_18.x); + if (fabsf(len) < 1e-6f) + { + v_18.x = 0; + v_18.y = 0; + v_18.z = 65536; + } + else + { + v_18.x = round_to_int((double)this->v_18.x / len * 65536.0); + v_18.y = round_to_int((double)this->v_18.y / len * 65536.0); + v_18.y = round_to_int((double)this->v_18.z / len * 65536.0); + } +} + +//----- (0048616B) -------------------------------------------------------- +void stru149::_48616B_frustum_odm(int a2, int a3, int a4, int a5, int a6, int a7) +{ + int v7; // ebx@1 + int v9; // edi@1 + int v11; // edx@1 + int v17; // ST0C_4@6 + int v19; // ST0C_4@9 + int v24; // [sp+14h] [bp-14h]@1 + int v25; // [sp+18h] [bp-10h]@1 + int v27; // [sp+24h] [bp-4h]@1 + + v25 = pGame->pIndoorCameraD3D->int_cosine_x; + v7 = pGame->pIndoorCameraD3D->int_sine_y; + v27 = pGame->pIndoorCameraD3D->int_sine_x; + //v8 = -pIndoorCamera->pos.y; + v9 = pGame->pIndoorCameraD3D->int_cosine_y; + //v26 = -pIndoorCamera->pos.z; + v11 = pGame->pIndoorCameraD3D->int_cosine_y * -pGame->pIndoorCameraD3D->vPartyPos.x + pGame->pIndoorCameraD3D->int_sine_y * -pGame->pIndoorCameraD3D->vPartyPos.y; + v24 = pGame->pIndoorCameraD3D->int_cosine_y * -pGame->pIndoorCameraD3D->vPartyPos.y - pGame->pIndoorCameraD3D->int_sine_y * -pGame->pIndoorCameraD3D->vPartyPos.x; + if (pGame->pIndoorCameraD3D->sRotationX) + { + this->field_0_party_dir_x = fixpoint_mul(v11, pGame->pIndoorCameraD3D->int_cosine_x) + + fixpoint_mul((-pGame->pIndoorCameraD3D->vPartyPos.z) << 16, pGame->pIndoorCameraD3D->int_sine_x); + this->field_4_party_dir_y = v24; + this->field_8_party_dir_z = fixpoint_mul((-pGame->pIndoorCameraD3D->vPartyPos.z) << 16, v25) - fixpoint_mul(v11, v27); + } + else + { + this->field_0_party_dir_x = v11; + this->field_4_party_dir_y = v24; + this->field_8_party_dir_z = (-pGame->pIndoorCameraD3D->vPartyPos.z) << 16; + } + + if (pGame->pIndoorCameraD3D->sRotationX) + { + v17 = fixpoint_mul(a2, v9) + fixpoint_mul(a3, v7); + + this->angle_from_north = fixpoint_mul(v17, v25) + fixpoint_mul(a4, v27); + this->angle_from_west = fixpoint_mul(a3, v9) - fixpoint_mul(a2, v7); + this->viewing_angle_from_west_east = fixpoint_mul(a4, v25) - fixpoint_mul(v17, v27); + } + else + { + this->angle_from_north = fixpoint_mul(a2, v9) + fixpoint_mul(a3, v7); + this->angle_from_west = fixpoint_mul(a3, v9) - fixpoint_mul(a2, v7); + this->viewing_angle_from_west_east = a4; + } + + if (pGame->pIndoorCameraD3D->sRotationX) + { + v19 = fixpoint_mul(a5, v9) + fixpoint_mul(a6, v7); + + this->angle_from_east = fixpoint_mul(v19, v25) + fixpoint_mul(a7, v27); + this->angle_from_south = fixpoint_mul(a6, v9) - fixpoint_mul(a5, v7); + this->viewing_angle_from_north_south = fixpoint_mul(a7, v25) - fixpoint_mul(v19, v27); + } + else + { + this->angle_from_east = fixpoint_mul(a5, v9) + fixpoint_mul(a6, v7); + this->angle_from_south = fixpoint_mul(a6, v9) - fixpoint_mul(a5, v7); + this->viewing_angle_from_north_south = a7; + } + + this->angle_from_east = -this->angle_from_east; + this->angle_from_south = -this->angle_from_south; + this->viewing_angle_from_north_south = -this->viewing_angle_from_north_south; + + this->field_24 = fixpoint_dot(this->angle_from_north, this->field_0_party_dir_x, + this->angle_from_west, this->field_4_party_dir_y, + this->viewing_angle_from_west_east, this->field_8_party_dir_z); + this->field_28 = fixpoint_dot(this->angle_from_east, this->field_0_party_dir_x, + this->angle_from_south, this->field_4_party_dir_y, + this->viewing_angle_from_north_south, this->field_8_party_dir_z); +} + +//----- (0048694B) -------------------------------------------------------- +void stru149::_48694B_frustum_sky() +{ + this->angle_from_east = -this->angle_from_east; + this->angle_from_south = -this->angle_from_south; + this->viewing_angle_from_north_south = -this->viewing_angle_from_north_south; + + this->field_24 = fixpoint_dot(this->angle_from_north, this->field_0_party_dir_x, + this->angle_from_west, this->field_4_party_dir_y, + this->viewing_angle_from_west_east, this->field_8_party_dir_z); + this->field_28 = fixpoint_dot(this->angle_from_east, this->field_0_party_dir_x, + this->angle_from_south, this->field_4_party_dir_y, + this->viewing_angle_from_north_south, this->field_8_party_dir_z); +} +