• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Render Izometric, top-down

Sekinpu

Member
Joined
Jul 7, 2020
Messages
34
Solutions
1
Reaction score
6

i have problem change this :
LUA:
void MapView::updateVisibleTiles()
{
    // there is no tile to render on invalid positions
    if (!m_posInfo.camera.isValid())
        return;

    // clear current visible tiles cache
    do {
        m_floors[m_floorMin].cachedVisibleTiles.clear();
    } while (++m_floorMin <= m_floorMax);

    m_lockedFirstVisibleFloor = m_floorViewMode == LOCKED ? m_posInfo.camera.z : -1;

    const uint8_t prevFirstVisibleFloor = m_cachedFirstVisibleFloor;

    if (m_lastCameraPosition != m_posInfo.camera) {
        if (m_lastCameraPosition.z != m_posInfo.camera.z) {
            onFloorChange(m_posInfo.camera.z, m_lastCameraPosition.z);
        }

        const uint8_t cachedFirstVisibleFloor = calcFirstVisibleFloor(m_floorViewMode != ALWAYS);
        m_cachedFirstVisibleFloor = cachedFirstVisibleFloor;
        m_cachedLastVisibleFloor = std::max<uint8_t>(cachedFirstVisibleFloor, calcLastVisibleFloor());

        m_floorMin = m_floorMax = m_posInfo.camera.z;
    }

    uint8_t cachedFirstVisibleFloor = m_cachedFirstVisibleFloor;
    if (m_floorViewMode == ALWAYS_WITH_TRANSPARENCY || canFloorFade()) {
        cachedFirstVisibleFloor = calcFirstVisibleFloor(false);
    }

    // Fading System by Kondra https://github.com/OTCv8/otclientv8
    if (!m_lastCameraPosition.isValid() || m_lastCameraPosition.z != m_posInfo.camera.z || m_lastCameraPosition.distance(m_posInfo.camera) >= 3) {
        m_fadeType = FadeType::NONE$;
        for (int iz = m_cachedLastVisibleFloor; iz >= cachedFirstVisibleFloor; --iz) {
            m_floors[iz].fadingTimers.restart(m_floorFading * 1000);
        }
    } else if (prevFirstVisibleFloor < m_cachedFirstVisibleFloor) { // hiding new floor
        m_fadeType = FadeType::OUT$;
        for (int iz = prevFirstVisibleFloor; iz < m_cachedFirstVisibleFloor; ++iz) {
            const int shift = std::max<int>(0, m_floorFading - m_floors[iz].fadingTimers.elapsed_millis());
            m_floors[iz].fadingTimers.restart(shift * 1000);
        }
    } else if (prevFirstVisibleFloor > m_cachedFirstVisibleFloor) { // showing floor
        m_fadeType = FadeType::IN$;
        m_fadeFinish = false;
        for (int iz = m_cachedFirstVisibleFloor; iz < prevFirstVisibleFloor; ++iz) {
            const int shift = std::max<int>(0, m_floorFading - m_floors[iz].fadingTimers.elapsed_millis());
            m_floors[iz].fadingTimers.restart(shift * 1000);
        }
    }

    m_lastCameraPosition = m_posInfo.camera;
    destroyHighlightTile();

    const bool fadeFinished = getFadeLevel(m_cachedFirstVisibleFloor) == 1.f;

    // cache visible tiles in draw order
    // draw from last floor (the lower) to first floor (the higher)
    const uint32_t numDiagonals = m_drawDimension.width() + m_drawDimension.height() - 1;
    for (int_fast32_t iz = m_cachedLastVisibleFloor; iz >= cachedFirstVisibleFloor; --iz) {
        auto& floor = m_floors[iz].cachedVisibleTiles;

        // loop through / diagonals beginning at top left and going to top right
        for (uint_fast32_t diagonal = 0; diagonal < numDiagonals; ++diagonal) {
            // loop current diagonal tiles
            const uint32_t advance = std::max<uint32_t >(diagonal - m_drawDimension.height(), 0);
            for (int iy = diagonal - advance, ix = advance; iy >= 0 && ix < m_drawDimension.width(); --iy, ++ix) {
                // position on current floor
                //TODO: check position limits
                Position tilePos = m_posInfo.camera.translated(ix - m_virtualCenterOffset.x, iy - m_virtualCenterOffset.y);
                // adjust tilePos to the wanted floor
                tilePos.coveredUp(m_posInfo.camera.z - iz);
                if (const auto& tile = g_map.getTile(tilePos)) {
                    // skip tiles that have nothing
                    if (!tile->isDrawable())
                        continue;

                    bool addTile = true;

                    if (fadeFinished) {
                        // skip tiles that are completely behind another tile
                        if (tile->isCompletelyCovered(m_cachedFirstVisibleFloor, m_resetCoveredCache)) {
                            if (m_floorViewMode != ALWAYS_WITH_TRANSPARENCY || (tilePos.z < m_posInfo.camera.z && tile->isCovered(m_cachedFirstVisibleFloor))) {
                                addTile = false;
                            }
                        }
                    }

                    if (addTile) {
                        floor.tiles.emplace_back(tile);
                        tile->onAddInMapView();
                    }

                    if (isDrawingLights() && tile->canShade())
                        floor.shades.emplace_back(tile);

                    if (addTile || !floor.shades.empty()) {
                        if (iz < m_floorMin)
                            m_floorMin = iz;
                        else if (iz > m_floorMax)
                            m_floorMax = iz;
                    }
                }
            }
        }
    }

    m_updateVisibleTiles = false;
    m_resetCoveredCache = false;
    updateHighlightTile(m_mousePosition);
}

to this :
Code:
void MapView::updateVisibleTiles()
{
    if (!m_posInfo.camera.isValid())
        return;

    do {
        m_floors[m_floorMin].cachedVisibleTiles.clear();
    } while (++m_floorMin <= m_floorMax);

    m_lockedFirstVisibleFloor = m_floorViewMode == LOCKED ? m_posInfo.camera.z : -1;
    const auto prevFirstVisibleFloor = m_cachedFirstVisibleFloor;

    if (m_lastCameraPosition != m_posInfo.camera) {
        if (m_lastCameraPosition.z != m_posInfo.camera.z) {
            onFloorChange(m_posInfo.camera.z, m_lastCameraPosition.z);
        }
        
        const auto cachedFirstVisibleFloor = calcFirstVisibleFloor(m_floorViewMode != ALWAYS);
        m_cachedFirstVisibleFloor = cachedFirstVisibleFloor;
        m_cachedLastVisibleFloor = std::max<uint8_t>(cachedFirstVisibleFloor, calcLastVisibleFloor());
        
        m_floorMin = m_floorMax = m_posInfo.camera.z;
    }

    auto cachedFirstVisibleFloor = m_cachedFirstVisibleFloor;
    if (m_floorViewMode == ALWAYS_WITH_TRANSPARENCY || canFloorFade()) {
        cachedFirstVisibleFloor = calcFirstVisibleFloor(false);
    }

    m_lastCameraPosition = m_posInfo.camera;
    destroyHighlightTile();

    const bool checkIsCovered = !g_gameConfig.isDrawingCoveredThings() && getFadeLevel(m_cachedFirstVisibleFloor) == 1.f;

    const uint32_t numRows = m_drawDimension.height();
    const uint32_t numCols = m_drawDimension.width();

    auto processTileGrid = [&](std::vector<FloorData>& floors) {
        for (int_fast32_t iz = cachedFirstVisibleFloor; iz <= m_cachedLastVisibleFloor; ++iz) {
            auto& floor = floors[iz].cachedVisibleTiles;
            
            for (uint32_t iy = 0; iy < numRows; ++iy) {
                for (uint32_t ix = 0; ix < numCols; ++ix) {
                    Position tilePos = m_posInfo.camera.translated(ix - m_virtualCenterOffset.x, iy - m_virtualCenterOffset.y);
                    tilePos.coveredUp(m_posInfo.camera.z - iz);

                    if (const auto& tile = g_map.getTile(tilePos)) {
                        if (!tile->isDrawable()) continue;

                        bool addTile = true;
                        if (checkIsCovered && tile->isCompletelyCovered(m_cachedFirstVisibleFloor, m_resetCoveredCache)) {
                            if (m_floorViewMode != ALWAYS_WITH_TRANSPARENCY || (tilePos.z < m_posInfo.camera.z && tile->isCovered(m_cachedFirstVisibleFloor))) {
                                addTile = false;
                            }
                        }

                        if (addTile) {
                            floor.tiles.emplace_back(tile);
                            tile->onAddInMapView();
                        }

                        if (isDrawingLights() && tile->canShade()) {
                            floor.shades.emplace_back(tile);
                        }

                        if (addTile || !floor.shades.empty()) {
                            if (iz < m_floorMin)
                                m_floorMin = iz;
                            else if (iz > m_floorMax)
                                m_floorMax = iz;
                        }
                    }
                }
            }
        }
    };

    if (m_multithreading) {
        static const int numThreads = g_asyncDispatcher.get_thread_count();
        static BS::multi_future<void> tasks(numThreads);
        tasks.clear();

        for (auto i = 0; i < numThreads; ++i) {
            for (auto& floor : m_floorThreads[i])
                floor.cachedVisibleTiles.clear();
            
            tasks.emplace_back(g_asyncDispatcher.submit_task([=, this] {
                processTileGrid(m_floorThreads[i]);
            }));
        }
        
        tasks.wait();
        
        for (auto fi = 0; fi < m_floors.size(); ++fi) {
            auto& floor = m_floors[fi];
            floor.cachedVisibleTiles.clear();
            
            for (auto i = 0; i < numThreads; ++i) {
                auto& floorThread = m_floorThreads[i][fi];
                floor.cachedVisibleTiles.tiles.insert(floor.cachedVisibleTiles.tiles.end(), std::make_move_iterator(floorThread.cachedVisibleTiles.tiles.begin()), std::make_move_iterator(floorThread.cachedVisibleTiles.tiles.end()));
                floor.cachedVisibleTiles.shades.insert(floor.cachedVisibleTiles.shades.end(), std::make_move_iterator(floorThread.cachedVisibleTiles.shades.begin()), std::make_move_iterator(floorThread.cachedVisibleTiles.shades.end()));
            }
        }
    } else {
        processTileGrid(m_floors);
    }

    m_updateVisibleTiles = false;
    m_resetCoveredCache = false;
    updateHighlightTile(m_mousePosition);
}

and all work good for sprites 32x32 but if creature have more square sprites then work like clean otclient
obraz_2025-06-01_234653937.webp1748815159135.webp
Post automatically merged:

Big sprites dont work as well like small
 
Last edited:

Similar threads

Back
Top