Ломается рендер сампа

kin4stat

mq-team
Автор темы
Всефорумный модератор
2,730
4,710
Ну тут расписывать много не надо. Как только начинаешь выводить на экран текст - преобразования Мировых координат в экранные будто резко перестают работать.
C++:
class CD3DFont
{
public:
    enum eTextAlignment {
        TEXTALIGNMENT_RIGHT,
        TEXTALIGNMENT_CENTER,
        TEXTALIGNMENT_LEFT,
    };

    void Print(const char* text, float x, float y, eTextAlignment orientation, int font, bool bordered, DWORD color, DWORD bcolor);

    bool Font();
    void AddFont(const char* Caption, float size, bool bold, bool italic);
    void ReaddFont(const char* Caption, float size, bool bold, bool italic, int font);
    void FontReset();
    void OnLostDevice();
    inline void SetDevice(LPDIRECT3DDEVICE9 pDev) { pDevice = pDev; }
    inline int DrawHeight (int font) const
    {
        D3DXFONT_DESC ret;
        pFont[font]->GetDesc(&ret);
        return ret.Height;
    };
    inline int DrawLength(const char* szText, int font)
    {
        RECT rcRect = { 0,0,0,0 };
        if (pFont[font])
        {
            // calculate required rect
            pFont[font]->DrawTextA(NULL, szText, strlen(szText), &rcRect, DT_CALCRECT,
                D3DCOLOR_XRGB(0, 0, 0));
        }

        // return width
        return rcRect.right - rcRect.left;
    }
private:
    LPDIRECT3DDEVICE9         pDevice;
    ID3DXFont* pFont[6];
    int FontNr = 0;
};
C++:
void CD3DFont::Print(const char* text, float x, float y, eTextAlignment orientation, int font, bool bordered, DWORD color, DWORD bcolor)
{
    RECT rect;

    switch (orientation)
    {
    case eTextAlignment::TEXTALIGNMENT_LEFT:
        SetRect(&rect, x, y, x, y);
        pFont[font]->DrawTextA(NULL, text, -1, &rect, DT_CENTER | DT_NOCLIP, color);
        break;
  
}
C++:
bool CD3DFont::Font()
{
    for (int i = 0; i < FontNr; i++)
        if (pFont[i]) return false;
    return (FontNr == 0) ? false : true;
}

void CD3DFont::ReaddFont(const char* Caption, float size, bool bold, bool italic, int font) {
    if (pFont[font]) {
        pFont[font]->Release();
        D3DXCreateFontA(pDevice, static_cast<INT>(size), 0, (bold) ? FW_BOLD : FW_NORMAL, 1, (italic) ? 1 : 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH, Caption, &pFont[font]);
    }
}

void CD3DFont::AddFont(const char* Caption, float size, bool bold, bool italic)
{
    D3DXCreateFontA(pDevice, static_cast<INT>(size), 0, (bold) ? FW_BOLD : FW_NORMAL, 1, (italic) ? 1 : 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH, Caption, &pFont[FontNr++]);
}

void CD3DFont::FontReset()
{
    for (int i = 0; i < FontNr; i++) pFont[i]->OnLostDevice();
    for (int i = 0; i < FontNr; i++) pFont[i]->OnResetDevice();
}
C++:
HRESULT __stdcall CD3DHook::Hooked_Reset(LPDIRECT3DDEVICE9 pDevice, D3DPRESENT_PARAMETERS *pPresentParams)
{
    if (!pD3DHook->pD3DFont->Font()) {
        pD3DHook->pD3DFont->FontReset();
    }
    HRESULT ret = pD3DHook->Orginal_Reset(pDevice, pPresentParams);
    if (ret == D3D_OK)
    {
        if (!pD3DHook->pD3DFont->Font()) {
            pD3DHook->pD3DFont->ReaddFont("GothamPro-Black", 0.0104166666666667f * *reinterpret_cast<int*>(0x00C17044), false, false, 0);
            pD3DHook->pD3DFont->ReaddFont("GothamPro-Black", 0.0078125f * *reinterpret_cast<int*>(0x00C17044), false, false, 1);
        }
    }
    return ret;
}
C++:
// Present Hook
pD3DHook->pD3DFont->Print("test", 200, 200, CD3DFont::TEXTALIGNMENT_LEFT, 1, false, D3DCOLOR_XRGB(0xEE, 0xB0, 0x07), 1);

C++:
// Выполняется единожды перед самым первым Present
pD3DHook->pD3DFont->AddFont("GothamPro-Black", 0.0104166666666667f * *reinterpret_cast<int*>(0x00C17044), false, false);
pD3DHook->pD3DFont->AddFont("Tahoma", 0.0078125f * *reinterpret_cast<int*>(0x00C17044), false, false);
А происходит вот такая дичь(смотреть в левый верхний угол. На белую полосу не обращайте внимания, приколы оконного режима):
1604964024886.png
 
Решение
При рисовании текста, матрицы преобразования изменяются таким образом, что мировые координаты становятся эквивалентны экранным. Самповские спрайты используют мировые координаты для указания своего положения, и, из-за того, что матрицы не восстановлены - происходит ... это...
Для исправления подобного поведения достаточно сохранить матрицу проекции перед рисованием, а по завершении - восстановить.
C++:
D3DMATRIX projection_matrix;
pDevice->GetTransform(D3DTS_PROJECTION, &projection_matrix);

// render

pDevice->SetTransform(D3DTS_PROJECTION, &projection_matrix);
И ещё, метод ID3DXFont::OnResetDevice() должен вызываться ПОСЛЕ сброса девайса.

redcode

🤔
Друг
144
1,258
При рисовании текста, матрицы преобразования изменяются таким образом, что мировые координаты становятся эквивалентны экранным. Самповские спрайты используют мировые координаты для указания своего положения, и, из-за того, что матрицы не восстановлены - происходит ... это...
Для исправления подобного поведения достаточно сохранить матрицу проекции перед рисованием, а по завершении - восстановить.
C++:
D3DMATRIX projection_matrix;
pDevice->GetTransform(D3DTS_PROJECTION, &projection_matrix);

// render

pDevice->SetTransform(D3DTS_PROJECTION, &projection_matrix);
И ещё, метод ID3DXFont::OnResetDevice() должен вызываться ПОСЛЕ сброса девайса.