Project To Screen Internal Rebuild (External)

Участник
Участник
Статус
Оффлайн
Регистрация
21 Сен 2019
Сообщения
595
Реакции
250
Поскольку я начал писать свой экстернал под эту увлекательную игру, мне потребовался так называемый "World To Screen", который оказалось не так просто сделать в этой уникальной игре. Было решено ребилднуть W2S функу игры.
Собственно почему бы не поделиться с другими, поскольку ничего особенного в этой базовой функции нет.

Ребилд произведен с помощью так называемой "IDA Pro 8.3" и имеющимися данными в виде дампа ласт версии и PDB 2019.

Непосредственно ProjectToScreenInternal был ребилднут с ласт дампа, mathVec3Project же я украл с PDB 2019, поскольку ребилд с ласт версии не захотел работать (ну и ладно).

Ко всем функциям и оффсетам прилагается сигнатура по которой будет очень просто обновиться в будущем.

Потребуется класс CRenderer, а точнее некоторые переменные из него - матрица, и вьюпорт.
C++:
Expand Collapse Copy
struct viewport_t {
  int x, y, z, w;
};

class c_renderer {
public:
  OFFSET(viewport_t, m_pViewPort(), 0x14B718); // BB 18 B7 14 00

public:
  /*
   * this->m_RP.m_TI[m_nCurThreadProcess].m_matView/m_matProj
   * @note: m_nCurThreadProcess is always 0, looks like anti-paste idk
   * 48 69 C8 28 03 00 00 0F 29 4C 24 70
   */
  cryengine_matrix4x4_t m_matViewTop() {
    auto m_matView =
        core->proc_read<std::uintptr_t>(core->proc_read<std::uintptr_t>(
            reinterpret_cast<std::uintptr_t>(this) + 0x328 + 0xF38));
    return core->proc_read<cryengine_matrix4x4_t>(m_matView); // m_matView->m_pTop
  }

  cryengine_matrix4x4_t m_matProjTop() {
    auto m_matProj =
        core->proc_read<std::uintptr_t>(core->proc_read<std::uintptr_t>(
            reinterpret_cast<std::uintptr_t>(this) + 0x328 + 0xF40));
    return core->proc_read<cryengine_matrix4x4_t>(m_matProj); // m_matProj->m_pTop
  }
};
Также структура матрицы и PTS.
C++:
Expand Collapse Copy
struct cryengine_matrix4x4_t {
  float m00, m01, m02, m03;
  float m10, m11, m12, m13;
  float m20, m21, m22, m23;
  float m30, m31, m32, m33;

  cryengine_matrix4x4_t() = default;

  void set_identity() {
    m00 = 1;
    m01 = 0;
    m02 = 0;
    m03 = 0;
    m10 = 0;
    m11 = 1;
    m12 = 0;
    m13 = 0;
    m20 = 0;
    m21 = 0;
    m22 = 1;
    m23 = 0;
    m30 = 0;
    m31 = 0;
    m32 = 0;
    m33 = 1;
  }

  void sanitaze() {
    if (!std::isfinite(m00))
      m00 = 0.f;
    if (!std::isfinite(m01))
      m01 = 0.f;
    if (!std::isfinite(m02))
      m02 = 0.f;
    if (!std::isfinite(m03))
      m03 = 0.f;
    if (!std::isfinite(m10))
      m10 = 0.f;
    if (!std::isfinite(m11))
      m11 = 0.f;
    if (!std::isfinite(m12))
      m12 = 0.f;
    if (!std::isfinite(m13))
      m13 = 0.f;
    if (!std::isfinite(m20))
      m20 = 0.f;
    if (!std::isfinite(m21))
      m21 = 0.f;
    if (!std::isfinite(m22))
      m22 = 0.f;
    if (!std::isfinite(m23))
      m23 = 0.f;
    if (!std::isfinite(m30))
      m30 = 0.f;
    if (!std::isfinite(m31))
      m31 = 0.f;
    if (!std::isfinite(m32))
      m32 = 0.f;
    if (!std::isfinite(m33))
      m33 = 0.f;
  }
};

struct project_to_screen_t {
  float ptx, pty, ptz; // project_to_N
  float sx, sy, sz; // screen_N
};

Псевдо-коды функций.
C++:
Expand Collapse Copy
char __fastcall ProjectToScreenInternal(__int64 a1, __int64 a2)
{
  _DWORD *v2; // rbx
  int v5; // ebp
  __int64 v6; // rbx
  DWORD CurrentThreadId; // eax
  bool v8; // al
  int v9; // xmm1_4
  int v10; // xmm0_4
  __int64 v11; // rbx
  int *v12; // rbx
  int v13; // r14d
  float *v14; // rax
  int v16[4]; // [rsp+30h] [rbp-78h] BYREF
  int v17[4]; // [rsp+40h] [rbp-68h] BYREF
  int v18[4]; // [rsp+50h] [rbp-58h] BYREF
  __int128 v19[4]; // [rsp+60h] [rbp-48h] BYREF

  v2 = *(_DWORD **)(a1 + 0x14B048);
  if ( GetCurrentThreadId() == v2[0x36] )
    v5 = v2[0xC];
  else
    v5 = v2[0xD];
  v6 = *(_QWORD *)(a1 + 0x14B048);
  CurrentThreadId = GetCurrentThreadId();
  v8 = CurrentThreadId == *(_DWORD *)(v6 + 0xDC) || CurrentThreadId == *(_DWORD *)(v6 + 0xD8);
  v9 = *(_DWORD *)(a2 + 4);
  v16[0] = *(_DWORD *)a2;
  v10 = *(_DWORD *)(a2 + 8);
  v11 = 0x14B718i64;
  if ( !v8 )
    v11 = 0x14B6D0i64;
  v16[1] = v9;
  v12 = (int *)(a1 + v11);
  v16[2] = v10;
  v19[0] = xmmword_141E74080;
  v13 = v12[2];
  v18[0] = *v12;
  v18[1] = v12[1];
  v18[3] = v12[3];
  v19[1] = xmmword_141E7EA80;
  v19[2] = xmmword_141E7EA90;
  v19[3] = xmmword_141E74100;
  v18[2] = v13;
  v14 = mathVec3Project(
          (float *)v17,
          (float *)v16,
          v18,
          **(float ***)(0x328i64 * v5 + a1 + 0xF40),
          **(float ***)(0x328i64 * v5 + a1 + 0xF38),
          (float *)v19);
  if ( v14 )
  {
    **(float **)(a2 + 0x10) = (float)(*(float *)v17 * *(float *)&dword_141E7404C) / (float)v13;
    **(float **)(a2 + 0x18) = (float)(*(float *)&v17[1] * *(float *)&dword_141E7404C) / (float)v12[3];
    **(_DWORD **)(a2 + 0x20) = v17[2];
    LOBYTE(v14) = 1;
  }
  return (char)v14;
}
C++:
Expand Collapse Copy
Vec3_tpl<float> *__fastcall mathVec3Project(
        Vec3_tpl<float> *pvWin,
        const Vec3_tpl<float> *pvObj,
        const int *pViewport,
        const Matrix44_tpl<float,XMVec4A> *pProjection,
        const Matrix44_tpl<float,XMVec4A> *pView,
        const Matrix44_tpl<float,XMVec4A> *pWorld)
{
  float v6; // xmm7_4
  float v7; // xmm8_4
  float v8; // xmm3_4
  float v9; // xmm2_4
  float v10; // xmm7_4
  float v11; // xmm4_4
  float v12; // xmm5_4
  float v13; // xmm6_4
  float v14; // xmm8_4
  Vec3_tpl<float> *result; // rax
  float v16; // xmm0_4
  float v17; // xmm2_4

  v6 = (float)((float)((float)(pvObj->y * pWorld->m11) + (float)(pvObj->x * pWorld->m01))
             + (float)(pvObj->z * pWorld->m21))
     + pWorld->m31;
  v7 = (float)((float)((float)(v6 * pView->m10)
                     + (float)((float)((float)((float)((float)(pvObj->y * pWorld->m10) + (float)(pvObj->x * pWorld->m00))
                                             + (float)(pvObj->z * pWorld->m20))
                                     + pWorld->m30)
                             * pView->m00))
             + (float)((float)((float)((float)((float)(pvObj->y * pWorld->m12) + (float)(pvObj->x * pWorld->m02))
                                     + (float)(pvObj->z * pWorld->m22))
                             + pWorld->m32)
                     * pView->m20))
     + (float)((float)((float)((float)((float)(pvObj->y * pWorld->m13) + (float)(pvObj->x * pWorld->m03))
                             + (float)(pvObj->z * pWorld->m23))
                     + pWorld->m33)
             * pView->m30);
  v8 = (float)((float)((float)(v6 * pView->m11)
                     + (float)((float)((float)((float)((float)(pvObj->y * pWorld->m10) + (float)(pvObj->x * pWorld->m00))
                                             + (float)(pvObj->z * pWorld->m20))
                                     + pWorld->m30)
                             * pView->m01))
             + (float)((float)((float)((float)((float)(pvObj->y * pWorld->m12) + (float)(pvObj->x * pWorld->m02))
                                     + (float)(pvObj->z * pWorld->m22))
                             + pWorld->m32)
                     * pView->m21))
     + (float)((float)((float)((float)((float)(pvObj->y * pWorld->m13) + (float)(pvObj->x * pWorld->m03))
                             + (float)(pvObj->z * pWorld->m23))
                     + pWorld->m33)
             * pView->m31);
  v9 = (float)((float)((float)(v6 * pView->m12)
                     + (float)((float)((float)((float)((float)(pvObj->y * pWorld->m10) + (float)(pvObj->x * pWorld->m00))
                                             + (float)(pvObj->z * pWorld->m20))
                                     + pWorld->m30)
                             * pView->m02))
             + (float)((float)((float)((float)((float)(pvObj->y * pWorld->m12) + (float)(pvObj->x * pWorld->m02))
                                     + (float)(pvObj->z * pWorld->m22))
                             + pWorld->m32)
                     * pView->m22))
     + (float)((float)((float)((float)((float)(pvObj->y * pWorld->m13) + (float)(pvObj->x * pWorld->m03))
                             + (float)(pvObj->z * pWorld->m23))
                     + pWorld->m33)
             * pView->m32);
  v10 = (float)((float)((float)(v6 * pView->m13)
                      + (float)((float)((float)((float)((float)(pvObj->y * pWorld->m10) + (float)(pvObj->x * pWorld->m00))
                                              + (float)(pvObj->z * pWorld->m20))
                                      + pWorld->m30)
                              * pView->m03))
              + (float)((float)((float)((float)((float)(pvObj->y * pWorld->m12) + (float)(pvObj->x * pWorld->m02))
                                      + (float)(pvObj->z * pWorld->m22))
                              + pWorld->m32)
                      * pView->m23))
      + (float)((float)((float)((float)((float)(pvObj->y * pWorld->m13) + (float)(pvObj->x * pWorld->m03))
                              + (float)(pvObj->z * pWorld->m23))
                      + pWorld->m33)
              * pView->m33);
  v11 = (float)((float)((float)(v8 * pProjection->m10) + (float)(v7 * pProjection->m00)) + (float)(v9 * pProjection->m20))
      + (float)(v10 * pProjection->m30);
  v12 = (float)((float)((float)(v8 * pProjection->m11) + (float)(v7 * pProjection->m01)) + (float)(v9 * pProjection->m21))
      + (float)(v10 * pProjection->m31);
  v13 = (float)((float)((float)(v7 * pProjection->m02) + (float)(v8 * pProjection->m12)) + (float)(v9 * pProjection->m22))
      + (float)(v10 * pProjection->m32);
  v14 = (float)((float)((float)(v7 * pProjection->m03) + (float)(v8 * pProjection->m13)) + (float)(v9 * pProjection->m23))
      + (float)(v10 * pProjection->m33);
  if ( v14 == 0.0 )
    return 0i64;
  result = pvWin;
  pvWin->x = (float)((float)((float)((float)(v11 / v14) + 1.0) * (float)pViewport[2]) * 0.5) + (float)*pViewport;
  v16 = (float)pViewport[1];
  v17 = (float)((float)(1.0 - (float)(v12 / v14)) * (float)pViewport[3]) * 0.5;
  pvWin->z = v13 / v14;
  pvWin->y = v17 + v16;
  return result;
}

Ребилд функций.
C++:
Expand Collapse Copy
bool ProjectToScreenInternal_Rebuild(i_renderer *_this,
                                     project_to_screen_t &proj) {
  // @xref: 48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 48 89 7C 24 20 41 56 48
  // 81 EC A0 00 00 00 48 8B 99

  int pViewport[4];             // [rsp+50h] [rbp-58h] BYREF

  fw::vec3_t pvWin{};
  fw::vec3_t pvObj = {proj.ptx, proj.pty, proj.ptz};

  auto m_pViewPort = _this->m_pViewPort();
  pViewport[0] = m_pViewPort.x;
  pViewport[1] = m_pViewPort.y;
  pViewport[2] = m_pViewPort.z;
  pViewport[3] = m_pViewPort.w;

  auto m_matView = _this->m_matViewTop();
  auto m_matProj = _this->m_matProjTop();
  cryengine_matrix4x4_t pWorld{};

  m_matView.sanitaze();
  m_matProj.sanitaze();
  pWorld.set_identity();

  fw::vec3_t result = mathVec3Project_Rebuild(pvWin, pvObj, pViewport, m_matProj,
                                   m_matView, pWorld);

  if (!result.empty()) {
    proj.sx = pvWin.x * 100.f / pViewport[2];
    proj.sy = pvWin.y * 100.f / pViewport[3];
    proj.sz = pvWin.z;
  }

  return !result.empty();
}
C++:
Expand Collapse Copy
fw::vec3_t mathVec3Project_Rebuild(fw::vec3_t &pvWin, const fw::vec3_t &pvObj,
                                   const int pViewport[4],
                                   const cryengine_matrix4x4_t &pProjection,
                                   const cryengine_matrix4x4_t &pView,
                                   const cryengine_matrix4x4_t &pWorld) {
  // @xref: 48 83 EC 38 48 8B 44 24 68

  float v6;  // xmm7_4
  float v7;  // xmm8_4
  float v8;  // xmm3_4
  float v9;  // xmm2_4
  float v10; // xmm7_4
  float v11; // xmm4_4
  float v12; // xmm5_4
  float v13; // xmm6_4
  float v14; // xmm8_4

  /*
   * matrix calculation
   * i don't understand how to normal reverse this shit, so i just pasted this
   * magic pseudocode :/
   */
  {
    v6 = pvObj.y * pWorld.m11 + pvObj.x * pWorld.m01 + pvObj.z * pWorld.m21 +
         pWorld.m31;

    v7 = v6 * pView.m10 +
         (pvObj.y * pWorld.m10 + pvObj.x * pWorld.m00 + pvObj.z * pWorld.m20 +
          pWorld.m30) *
             pView.m00 +
         (pvObj.y * pWorld.m12 + pvObj.x * pWorld.m02 + pvObj.z * pWorld.m22 +
          pWorld.m32) *
             pView.m20 +
         (pvObj.y * pWorld.m13 + pvObj.x * pWorld.m03 + pvObj.z * pWorld.m23 +
          pWorld.m33) *
             pView.m30;
    v8 = v6 * pView.m11 +
         (pvObj.y * pWorld.m10 + pvObj.x * pWorld.m00 + pvObj.z * pWorld.m20 +
          pWorld.m30) *
             pView.m01 +
         (pvObj.y * pWorld.m12 + pvObj.x * pWorld.m02 + pvObj.z * pWorld.m22 +
          pWorld.m32) *
             pView.m21 +
         (pvObj.y * pWorld.m13 + pvObj.x * pWorld.m03 + pvObj.z * pWorld.m23 +
          pWorld.m33) *
             pView.m31;
    v9 = v6 * pView.m12 +
         (pvObj.y * pWorld.m10 + pvObj.x * pWorld.m00 + pvObj.z * pWorld.m20 +
          pWorld.m30) *
             pView.m02 +
         (pvObj.y * pWorld.m12 + pvObj.x * pWorld.m02 + pvObj.z * pWorld.m22 +
          pWorld.m32) *
             pView.m22 +
         (pvObj.y * pWorld.m13 + pvObj.x * pWorld.m03 + pvObj.z * pWorld.m23 +
          pWorld.m33) *
             pView.m32;
    v10 = v6 * pView.m13 +
          (pvObj.y * pWorld.m10 + pvObj.x * pWorld.m00 + pvObj.z * pWorld.m20 +
           pWorld.m30) *
              pView.m03 +
          (pvObj.y * pWorld.m12 + pvObj.x * pWorld.m02 + pvObj.z * pWorld.m22 +
           pWorld.m32) *
              pView.m23 +
          (pvObj.y * pWorld.m13 + pvObj.x * pWorld.m03 + pvObj.z * pWorld.m23 +
           pWorld.m33) *
              pView.m33;

    v11 = v8 * pProjection.m10 + v7 * pProjection.m00 + v9 * pProjection.m20 +
          v10 * pProjection.m30;
    v12 = v8 * pProjection.m11 + v7 * pProjection.m01 + v9 * pProjection.m21 +
          v10 * pProjection.m31;
    v13 = v7 * pProjection.m02 + v8 * pProjection.m12 + v9 * pProjection.m22 +
          v10 * pProjection.m32;
    v14 = v7 * pProjection.m03 + v8 * pProjection.m13 + v9 * pProjection.m23 +
          v10 * pProjection.m33;
  }

  if (v14 == 0.f)
    return {};

  pvWin.x = ((v11 / v14) + 1.f) * (static_cast<float>(pViewport[2]) * .5f) +
            static_cast<float>(pViewport[0]);
  pvWin.y = ((1.f - (v12 / v14)) * static_cast<float>(pViewport[3]) * .5f) +
            static_cast<float>(pViewport[1]);
  pvWin.z = v13 / v14;

  return pvWin;
}

Ну и сам World To Screen.
C++:
Expand Collapse Copy
bool world_to_screen(const fw::vec3_t &in, fw::vec3_t &out) {
  /*
   * here you need to get the address of SSystemGlobalEnvironment structure and screen_size
   */
  {
    /* removed */
  }

  project_to_screen_t pts{in.x, in.y, in.z, out.x, out.y, out.z};
  if (!ProjectToScreenInternal_Rebuild(sge->pRenderer(), pts))
    return false;

  if (pts.sz > 1.f) // behind camera
    return false;

  out.x = pts.sx * (screen_size.x / 100.f);
  out.y = pts.sy * (screen_size.y / 100.f);

  return true;
}

Отмечу, что это просто ребилд, и код можно(и я бы сказал нужно) привести в более презентабельный вид.
Этот ребилд также можно использовать для интернал софтов, если есть такая необходимость, но я делал под свой экстернал.
 
Последнее редактирование:
респект++
 
Дополнение к теме.
Юзер с ЮЦ чутка дополнил мою тему там дав нормальный mathVec3Project с оригинального движка, и привел ProjectToScreenInternal_Rebuild в более лучший вид.
Можете брать, кому надо.
C++:
Expand Collapse Copy
struct viewport_t {
  int x, y, w, h;
};

inline void mathVec4Transform(float out[4], const float m[16],
                              const float in[4]) {
#define M(row, col) m[col * 4 + row]
  out[0] =
      M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];
  out[1] =
      M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];
  out[2] =
      M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];
  out[3] =
      M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];
#undef M
}

inline float mathVec3Project(fw::vec3_t &pvWin, const fw::vec3_t &pvObj,
                             const viewport_t pViewport,
                             const cryengine_matrix4x4_t *pProjection,
                             const cryengine_matrix4x4_t *pView,
                             const cryengine_matrix4x4_t *pWorld) {
  // @xref
  // https://github.com/MergHQ/CRYENGINE/blob/8b63f61c6bb186fbee254b793775856468df47c5/Code/CryEngine/CryCommon/CryMath/Cry_XOptimise.h#L310

  fw::vec4_t in{}, out{};

  in.x = pvObj.x;
  in.y = pvObj.y;
  in.z = pvObj.z;
  in.w = 1.0f;

  mathVec4Transform(
      reinterpret_cast<float *>(&out),
      const_cast<float *>(reinterpret_cast<const float *>(pWorld)),
      reinterpret_cast<float *>(&in));
  mathVec4Transform(reinterpret_cast<float *>(&in),
                    const_cast<float *>(reinterpret_cast<const float *>(pView)),
                    reinterpret_cast<float *>(&out));
  mathVec4Transform(
      reinterpret_cast<float *>(&out),
      const_cast<float *>(reinterpret_cast<const float *>(pProjection)),
      reinterpret_cast<float *>(&in));

  if (out.w == 0.f)
    return 0.f;

  out.x /= out.w;
  out.y /= out.w;
  out.z /= out.w;

  pvWin.x = pViewport.x + (1.f + out.x) * pViewport.w / 2.f;
  pvWin.y = pViewport.y + (1.f - out.y) * pViewport.h / 2.f;
  pvWin.z = out.z;

  return out.w;
}
C++:
Expand Collapse Copy
bool ProjectToScreenInternal_Rebuild(i_renderer *_this, float ptx, float pty,
                                     float ptz, float &sx, float &sy,
                                     float &sz) {
  // @xref: 48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 48 89 7C 24 20 41 56 48
  // 81 EC A0 00 00 00 48 8B 99

  fw::vec3_t out{};
  fw::vec3_t in = {ptx, pty, ptz};

  auto viewport = _this->m_pViewPort();
  auto matrix_view = _this->m_matViewTop();
  auto matrix_projection = _this->m_matProjTop();
  cryengine_matrix4x4_t matrix_world{};

  matrix_view.sanitaze();
  matrix_projection.sanitaze();
  matrix_world.set_identity();

  if (mathVec3Project(out, in, viewport, &matrix_projection, &matrix_view,
                      &matrix_world) == 0.f)
    return false;

  sx = out.x * 100.f / viewport.w;
  sy = out.y * 100.f / viewport.h;
  sz = out.z;

  return true;
}
 
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
а есть сурс экстернала, можно под прошлые обновы, что бы можно было поучиться обновлять его под ласт версию
 
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Поделись определением sanitaze(), пожалуйста. В сдк Matrix44 не нашел данной фанки
 
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Поделись определением sanitaze(), пожалуйста. В сдк Matrix44 не нашел данной фанки
лучше открой uc и возьми все готовое из коммента к его теме чем пытаться понять этот бред
 
Назад
Сверху Снизу