static DWORD64 dwViewMatrix = 0x142407818;
static DWORD64 dwBaseProjection = dwViewMatrix + 0x40;
ststatic Vec3 mathVec3Project_Rebuild(Vec3& pvWin, const Vec3& pvObj, const int pViewport[4], const Matrix44& pProjection, const Matrix44& pView, const Matrix44& pWorld)
{
// Промежуточные переменные
float x = pvObj.x, y = pvObj.y, z = pvObj.z;
// Преобразование объекта в пространство мира
float w = x * pWorld.m[0][3] + y * pWorld.m[1][3] + z * pWorld.m[2][3] + pWorld.m[3][3];
float vX = x * pWorld.m[0][0] + y * pWorld.m[1][0] + z * pWorld.m[2][0] + pWorld.m[3][0];
float vY = x * pWorld.m[0][1] + y * pWorld.m[1][1] + z * pWorld.m[2][1] + pWorld.m[3][1];
float vZ = x * pWorld.m[0][2] + y * pWorld.m[1][2] + z * pWorld.m[2][2] + pWorld.m[3][2];
float vW = x * pWorld.m[0][3] + y * pWorld.m[1][3] + z * pWorld.m[2][3] + pWorld.m[3][3];
// Преобразование в пространство камеры
float pX = vX * pView.m[0][0] + vY * pView.m[1][0] + vZ * pView.m[2][0] + vW * pView.m[3][0];
float pY = vX * pView.m[0][1] + vY * pView.m[1][1] + vZ * pView.m[2][1] + vW * pView.m[3][1];
float pZ = vX * pView.m[0][2] + vY * pView.m[1][2] + vZ * pView.m[2][2] + vW * pView.m[3][2];
float pW = vX * pView.m[0][3] + vY * pView.m[1][3] + vZ * pView.m[2][3] + vW * pView.m[3][3];
// Преобразование в пространство проекции
float projX = pX * pProjection.m[0][0] + pY * pProjection.m[1][0] + pZ * pProjection.m[2][0] + pW * pProjection.m[3][0];
float projY = pX * pProjection.m[0][1] + pY * pProjection.m[1][1] + pZ * pProjection.m[2][1] + pW * pProjection.m[3][1];
float projZ = pX * pProjection.m[0][2] + pY * pProjection.m[1][2] + pZ * pProjection.m[2][2] + pW * pProjection.m[3][2];
float projW = pX * pProjection.m[0][3] + pY * pProjection.m[1][3] + pZ * pProjection.m[2][3] + pW * pProjection.m[3][3];
// Проверка на деление на ноль
if (projW == 0.0f)
return {};
// Нормализация и преобразование в экранные координаты
pvWin.x = ((projX / projW) + 1.0f) * (pViewport[2] * 0.5f) + pViewport[0];
pvWin.y = ((1.0f - (projY / projW)) * (pViewport[3] * 0.5f)) + pViewport[1];
pvWin.z = projZ / projW;
return pvWin;
template<class cData>
inline cData TGetValue(int64 dwOffset)
{
return Read<cData>(dwOffset);
}
class MatrixManager
{
public:
Matrix44 ProjectionMatrix;
Matrix44 ViewMatrix;
bool isProjectionMatrixUpdated;
bool isViewMatrixUpdated;
MatrixManager()
: isProjectionMatrixUpdated(false), isViewMatrixUpdated(false)
{}
// Обновление матрицы проекции
void UpdateProjectionMatrix()
{
Matrix44 newProjectionMatrix = TGetValue<Matrix44>(_IRenderer::dwBaseProjection);
if (newProjectionMatrix != ProjectionMatrix)
{
ProjectionMatrix = newProjectionMatrix;
isProjectionMatrixUpdated = true;
}
else
{
isProjectionMatrixUpdated = false;
}
}
// Обновление матрицы вида
void UpdateViewMatrix()
{
Matrix44 newViewMatrix = TGetValue<Matrix44>(_IRenderer::dwViewMatrix);
if (newViewMatrix != ViewMatrix)
{
ViewMatrix = newViewMatrix;
isViewMatrixUpdated = true;
}
else
{
isViewMatrixUpdated = false;
}
}
void UpdateMatrices()
{
UpdateProjectionMatrix();
UpdateViewMatrix();
}
};
// Глобальный объект для управления матрицами
MatrixManager g_MatrixManager;
inline bool ProjectToScreen2(int32* vp, const Vec3& ptx, Vec3& sx)
{
// Обновление матриц только при необходимости
g_MatrixManager.UpdateMatrices();
Vec3 vOut;
Matrix44 mIdent;
mIdent.SetIdentity();
// Использование матриц из глобального объекта
Vec3 result = mathVec3Project_Rebuild(vOut, ptx, vp, g_MatrixManager.ProjectionMatrix, g_MatrixManager.ViewMatrix, mIdent);
if (!result.IsEmpty())
{
sx.x = vOut.x * 100.0f / static_cast<float>(vp[2]);
sx.y = vOut.y * 100.0f / static_cast<float>(vp[3]);
sx.z = vOut.z;
return true;
}
return false;
}
}