Отрисовка модели

chapo

чопа сребдс // TG/IG: @moujeek
Автор темы
Модератор
9,018
11,849
Версия MoonLoader
.026-beta
че
1650570040756.png


использую данный сниппет: https://www.blast.hk/threads/13380/post-996590
почему при отрисовке модели 487 вместо текстуры маверика отображается чат?
@kin4stat хелп пж
Lua:
-- mimgui
            if imgui.Selectable(tostring(k)..'. '..v[1]..' ('..tostring(v[2])..')'..' >> '..(vehicles[selectedModelNew] and vehicles[selectedModelNew][1] or u8'Не выбрано'), selected_my == k) then
                selected_my = k
                PREVIEW.my = render_model(tonumber(getVehileModelByName(v[1])) or 411, PREVIEW_SETTINGS)
                sampAddChatMessage(getVehileModelByName(v[1]), -1)
            end
            
-- getVehileModelByName
function getVehileModelByName(name)
    for k, v in ipairs(vehicles) do
        if name:lower():find(v[1]:lower()) then
            return v[2]
        end
    end
    return 411
end
даже если заменить tonumber(getVehileModelByName(v[1])) or 411 на 487, то такая дичь остается:
1650570195796.png
 

kin4stat

mq-team · kin4@naebalovo.team
Всефорумный модератор
2,748
4,849
че
Посмотреть вложение 144474

использую данный сниппет: https://www.blast.hk/threads/13380/post-996590
почему при отрисовке модели 487 вместо текстуры маверика отображается чат?
@kin4stat хелп пж
Lua:
-- mimgui
            if imgui.Selectable(tostring(k)..'. '..v[1]..' ('..tostring(v[2])..')'..' >> '..(vehicles[selectedModelNew] and vehicles[selectedModelNew][1] or u8'Не выбрано'), selected_my == k) then
                selected_my = k
                PREVIEW.my = render_model(tonumber(getVehileModelByName(v[1])) or 411, PREVIEW_SETTINGS)
                sampAddChatMessage(getVehileModelByName(v[1]), -1)
            end
           
-- getVehileModelByName
function getVehileModelByName(name)
    for k, v in ipairs(vehicles) do
        if name:lower():find(v[1]:lower()) then
            return v[2]
        end
    end
    return 411
end
даже если заменить tonumber(getVehileModelByName(v[1])) or 411 на 487, то такая дичь остается:
Посмотреть вложение 144475
C PREVIEW_SETTINGS точно все ок
 

chapo

чопа сребдс // TG/IG: @moujeek
Автор темы
Модератор
9,018
11,849
C PREVIEW_SETTINGS точно все ок
у меня в менюшке 2 модели, с 1 все норм, а со второй такая ебень
Lua:
local PREVIEW_SETTINGS = {
    ["background_color"] = 0x00000000,
    ["zoom"] = 0.9,
    ["rotation"] = { ["x"] = 340, ["y"] = 0, ["z"] = 45 },
    ["carc_1"] = 1,
    ["carc_2"] = 1
}
1650570534608.png
 

четыреста четыре

Известный
120
20
заметл такое поведение, когда во время загрузки скрипта кто-то или что-то пишет в чат получатеся такая хуйня

заметл такое поведение, когда во время загрузки скрипта кто-то или что-то пишет в чат получатеся такая хуйня
то есть если во время подгрузки этой ебаной модели появится сообщение в чате получится такая дичь

Lua:
sampSetChatDisplayMode(0)
for i=1, #render_models do
    local id = render_models[i]
    loadtexture(id)
end
wait(33)
sampSetChatDisplayMode(3)

ебать какой костыль, но все же лучше чем ничего
 
Последнее редактирование:

ChаtGPT

Активный
400
96
Очень даже..актуально..
Я нашёл 2 проблемы и без понятия как их фиксить.
(Я смотрел разные исходники, там всё одинаково и проблема тоже одинакова)
Lua:
local ffi = require 'ffi'
local imgui = require 'mimgui'

local MODEL_INFO_ATOMIC = 1
local MODEL_INFO_TIME = 3
local MODEL_INFO_WEAPON = 4
local MODEL_INFO_CLUMP = 5
local MODEL_INFO_VEHICLE = 6
local MODEL_INFO_PED = 7
local MODEL_INFO_LOD = 8

ffi.cdef [[
    typedef unsigned char RwUInt8;
    typedef int RwInt32;
    typedef short RwInt16;

    struct RwRaster {
        struct RwRaster             *parent;
        RwUInt8                     *cpPixels;
        RwUInt8                     *palette;
        RwInt32                     width, height, depth;
        RwInt32                     stride;
        RwInt16                     nOffsetX, nOffsetY;
        RwUInt8                     cType;
        RwUInt8                     cFlags;
        RwUInt8                     privateFlags;
        RwUInt8                     cFormat;
        RwUInt8                     *originalPixels;
        RwInt32                      originalWidth;
        RwInt32                      originalHeight;
        RwInt32                      originalStride;
        void*                       texture_ptr;
    };

    struct RwTexture {
        struct RwRaster* raster;
    };

    struct CBaseModelInfo_vtbl {
        void* destructor;
        void* AsAtomicModelInfoPtr;
        void* AsDamageAtomicModelInfoPtr;
        void* AsLodAtomicModelInfoPtr;
        char(__thiscall* GetModelType)(struct CBaseModelInfo*);
    };

    struct CBaseModelInfo {
        struct CBaseModelInfo_vtbl* vtbl;
    };

    typedef struct RwTexture*(__thiscall* vehicle_render_t)(unsigned long, int, int, float*, float, int, int);
    typedef struct RwTexture*(__thiscall* ped_render_t)(unsigned long, int, int, float*, float);
    typedef struct RwTexture*(__thiscall* others_render_t)(unsigned long, int, int, float*, float);
]]

local RwTextureDestroy = ffi.cast("int(__cdecl*)(struct RwTexture*)", 0x7F3820)
local GetModelInfo = ffi.cast("struct CBaseModelInfo*(__cdecl*)(int)", 0x403DA0)

local textures_from_render = {}

function render_ond3d_lost()
    for i = 1, #textures_from_render do
        RwTextureDestroy(textures_from_render[i])
    end
end

function render_model(model_id, params)
    if 0 > model_id or model_id >= 20000 then return nil end

    local backcolor = params["background_color"]
    local zoom = params["zoom"]
    local rot = params["rotation"]
    local rotation = ffi.new("float [3]")
    rotation[0] = rot.x
    rotation[1] = rot.y
    rotation[2] = rot.z

    local offsets = {
        ["vehicle"]   = { ["R1"] = 0x2EE4E5, ["R3"] = 0x6BC50 },
        ["ped"]       = { ["R1"] = 0x2F522D, ["R3"] = 0x6B9D0 },
        ["others"]    = { ["R1"] = 0x2BE702, ["R3"] = 0x6C240 },
        ["sampst"]    = { ["R1"] = 0x21A108, ["R3"] = 0x26E8F0 }
    }
    local vSAMP = getGameGlobal(707) <= 21 and "R1" or "R3"

    local model_info = GetModelInfo(model_id);
    if model_info ~= ffi.NULL then
        local model_type = model_info.vtbl.GetModelType(model_info);
        local sampst = ffi.cast("unsigned long*", sampGetBase() + offsets["sampst"][vSAMP])[0]

        local result = ffi.NULL
        if model_type == MODEL_INFO_VEHICLE then
            local func_addr = sampGetBase() + offsets["vehicle"][vSAMP]
            result = ffi.cast("vehicle_render_t", func_addr)(sampst, model_id, backcolor,  rotation, zoom, params["carc_1"], params["carc_2"])
        elseif model_type == MODEL_INFO_PED then
            local func_addr = sampGetBase() + offsets["ped"][vSAMP]
            result = ffi.cast("ped_render_t", func_addr)(sampst, model_id, backcolor,  rotation, zoom)
        elseif model_type == MODEL_INFO_WEAPON or model_type == MODEL_INFO_ATOMIC or model_type == MODEL_INFO_CLUMP then
            local func_addr = sampGetBase() + offsets["others"][vSAMP]
            result = ffi.cast("others_render_t", func_addr)(sampst, model_id, backcolor,  rotation, zoom)
        else
            return nil
        end
        if result ~= ffi.NULL and result.raster ~= ffi.NULL and result.raster.texture_ptr ~= ffi.NULL then
            textures_from_render[#textures_from_render + 1] = result
            return result.raster.texture_ptr
        end
        return nil
    end
end


local texture = nil

imgui.OnFrame(
    function() return true end,
    function(self)

        if imgui.Button("Update") then
            texture = render_model(0, {
                ["background_color"] = 0x00000000,
                ["zoom"] = 1,
                ["rotation"] = { ["x"] = 0, ["y"] = 0, ["z"] = 0 },
                ["carc_1"] = 0,
                ["carc_2"] = 1
            })
        end

        --if not texture then
        --    texture = render_model(0, {
        --        ["background_color"] = 0x00000000,
        --        ["zoom"] = 1,
        --        ["rotation"] = { ["x"] = 0, ["y"] = 0, ["z"] = 0 },
        --        ["carc_1"] = 0,
        --        ["carc_2"] = 1
        --    })
        --end

        if texture then
            imgui.Image(texture, imgui.ImVec2(256, 256))
        end
    end
)

function onD3DDeviceLost()
    render_ond3d_lost()
    texture = nil
end
1. Если обновлять модельку через imgui.Button("Update") и переместить окно в левую сторону к чату, вместо модельки будет отображаться рекурсия текущего окна. (Демонстрация)

2. Если использовать if not texture then (создать текстуру, если её нету), то при сворачивании игры, а позже при разворачивании, вместо модельки, рендерится чат. При этом, сам чат пропадает (нажать F7, чтобы его снова отобразить).

1734541457609.png


2.1. Если перед сворачиванием игры скрыть чат, свернуть игру, развернуть игру:
(рендерит нормер машины, 🤔)

1734542593944.png



@kin4stat
 
Последнее редактирование:

chapo

чопа сребдс // TG/IG: @moujeek
Автор темы
Модератор
9,018
11,849
Очень даже..актуально..
Я нашёл 2 проблемы и без понятия как их фиксить.
(Я смотрел разные исходники, там всё одинаково и проблема тоже одинакова)
Lua:
local ffi = require 'ffi'
local imgui = require 'mimgui'

local MODEL_INFO_ATOMIC = 1
local MODEL_INFO_TIME = 3
local MODEL_INFO_WEAPON = 4
local MODEL_INFO_CLUMP = 5
local MODEL_INFO_VEHICLE = 6
local MODEL_INFO_PED = 7
local MODEL_INFO_LOD = 8

ffi.cdef [[
    typedef unsigned char RwUInt8;
    typedef int RwInt32;
    typedef short RwInt16;

    struct RwRaster {
        struct RwRaster             *parent;
        RwUInt8                     *cpPixels;
        RwUInt8                     *palette;
        RwInt32                     width, height, depth;
        RwInt32                     stride;
        RwInt16                     nOffsetX, nOffsetY;
        RwUInt8                     cType;
        RwUInt8                     cFlags;
        RwUInt8                     privateFlags;
        RwUInt8                     cFormat;
        RwUInt8                     *originalPixels;
        RwInt32                      originalWidth;
        RwInt32                      originalHeight;
        RwInt32                      originalStride;
        void*                       texture_ptr;
    };

    struct RwTexture {
        struct RwRaster* raster;
    };

    struct CBaseModelInfo_vtbl {
        void* destructor;
        void* AsAtomicModelInfoPtr;
        void* AsDamageAtomicModelInfoPtr;
        void* AsLodAtomicModelInfoPtr;
        char(__thiscall* GetModelType)(struct CBaseModelInfo*);
    };

    struct CBaseModelInfo {
        struct CBaseModelInfo_vtbl* vtbl;
    };

    typedef struct RwTexture*(__thiscall* vehicle_render_t)(unsigned long, int, int, float*, float, int, int);
    typedef struct RwTexture*(__thiscall* ped_render_t)(unsigned long, int, int, float*, float);
    typedef struct RwTexture*(__thiscall* others_render_t)(unsigned long, int, int, float*, float);
]]

local RwTextureDestroy = ffi.cast("int(__cdecl*)(struct RwTexture*)", 0x7F3820)
local GetModelInfo = ffi.cast("struct CBaseModelInfo*(__cdecl*)(int)", 0x403DA0)

local textures_from_render = {}

function render_ond3d_lost()
    for i = 1, #textures_from_render do
        RwTextureDestroy(textures_from_render[i])
    end
end

function render_model(model_id, params)
    if 0 > model_id or model_id >= 20000 then return nil end

    local backcolor = params["background_color"]
    local zoom = params["zoom"]
    local rot = params["rotation"]
    local rotation = ffi.new("float [3]")
    rotation[0] = rot.x
    rotation[1] = rot.y
    rotation[2] = rot.z

    local offsets = {
        ["vehicle"]   = { ["R1"] = 0x2EE4E5, ["R3"] = 0x6BC50 },
        ["ped"]       = { ["R1"] = 0x2F522D, ["R3"] = 0x6B9D0 },
        ["others"]    = { ["R1"] = 0x2BE702, ["R3"] = 0x6C240 },
        ["sampst"]    = { ["R1"] = 0x21A108, ["R3"] = 0x26E8F0 }
    }
    local vSAMP = getGameGlobal(707) <= 21 and "R1" or "R3"

    local model_info = GetModelInfo(model_id);
    if model_info ~= ffi.NULL then
        local model_type = model_info.vtbl.GetModelType(model_info);
        local sampst = ffi.cast("unsigned long*", sampGetBase() + offsets["sampst"][vSAMP])[0]

        local result = ffi.NULL
        if model_type == MODEL_INFO_VEHICLE then
            local func_addr = sampGetBase() + offsets["vehicle"][vSAMP]
            result = ffi.cast("vehicle_render_t", func_addr)(sampst, model_id, backcolor,  rotation, zoom, params["carc_1"], params["carc_2"])
        elseif model_type == MODEL_INFO_PED then
            local func_addr = sampGetBase() + offsets["ped"][vSAMP]
            result = ffi.cast("ped_render_t", func_addr)(sampst, model_id, backcolor,  rotation, zoom)
        elseif model_type == MODEL_INFO_WEAPON or model_type == MODEL_INFO_ATOMIC or model_type == MODEL_INFO_CLUMP then
            local func_addr = sampGetBase() + offsets["others"][vSAMP]
            result = ffi.cast("others_render_t", func_addr)(sampst, model_id, backcolor,  rotation, zoom)
        else
            return nil
        end
        if result ~= ffi.NULL and result.raster ~= ffi.NULL and result.raster.texture_ptr ~= ffi.NULL then
            textures_from_render[#textures_from_render + 1] = result
            return result.raster.texture_ptr
        end
        return nil
    end
end


local texture = nil

imgui.OnFrame(
    function() return true end,
    function(self)

        if imgui.Button("Update") then
            texture = render_model(0, {
                ["background_color"] = 0x00000000,
                ["zoom"] = 1,
                ["rotation"] = { ["x"] = 0, ["y"] = 0, ["z"] = 0 },
                ["carc_1"] = 0,
                ["carc_2"] = 1
            })
        end

        --if not texture then
        --    texture = render_model(0, {
        --        ["background_color"] = 0x00000000,
        --        ["zoom"] = 1,
        --        ["rotation"] = { ["x"] = 0, ["y"] = 0, ["z"] = 0 },
        --        ["carc_1"] = 0,
        --        ["carc_2"] = 1
        --    })
        --end

        if texture then
            imgui.Image(texture, imgui.ImVec2(256, 256))
        end
    end
)

function onD3DDeviceLost()
    render_ond3d_lost()
    texture = nil
end
1. Если обновлять модельку через imgui.Button("Update") и переместить окно в левую сторону к чату, вместо модельки будет отображаться рекурсия текущего окна. (Демонстрация)

2. Если использовать if not texture then (создать текстуру, если её нету), то при сворачивании игры, а позже при разворачивании, вместо модельки, рендерится чат. При этом, сам чат пропадает (нажать F7, чтобы его снова отобразить).

Посмотреть вложение 259760

@kin4stat
загружать модельки нужно вне функции мимгуя, например так
Lua:
local textures = {};
local textureQueue = {};

-- frame
imgui.Image(textures[411], ...);
if (imgui.Button('update')) then
    table.insert(textureQueue, 411);
end

-- main loop
if (#textureQueue > 0) then
    for index, model in ipairs(textureQueue) do
        textures[model] = render_model(model, ...);
    end
    textureQueue = {}
end
 
  • Нравится
Реакции: ChаtGPT и cloused2

ChаtGPT

Активный
400
96
загружать модельки нужно вне функции мимгуя, например так
Lua:
local textures = {};
local textureQueue = {};

-- frame
imgui.Image(textures[411], ...);
if (imgui.Button('update')) then
    table.insert(textureQueue, 411);
end

-- main loop
if (#textureQueue > 0) then
    for index, model in ipairs(textureQueue) do
        textures[model] = render_model(model, ...);
    end
    textureQueue = {}
end
Да, это решило все проблемы, спасибо. Только не нравится, что модельки будут загружаться даже тогда, когда это и не нужно(когда скрипт не используется). Хотя, можно проверки разные добавить, на видимость окна и если таблица с текстурками не пуста. К слову об этом, почему нужно вызывать onD3DDeviceLost и удалять все текстурки? Можно ли использовать тогда onD3DPresent() для обратного создания текстур, вместо беск.цикла в main. onD3DPresent() вроде быстрее обработал, или он предназначен для более легких задач, чем парс? Просто мне кажется, немного не правильно то, что при разворачивании игры нужно обратно подгружать все модельки, ибо после сворачивания - они слетают.
У меня рендерится несколько текстур в окне без кнопки апдейт и после разворачивании игры, нужно их обратно создать.

Я такие функции просто не использовал.

Как можно довести до ума?
 
Последнее редактирование: