mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 03:26:39 +00:00 
			
		
		
		
	cellSize > 1 so the result of the division cannot be undefined.
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:18:35: error: The result of the '/' expression is undefined [clang-analyzer-core.UndefinedBinaryOperatorResult,-warnings-as-errors]
   18 |         std::size_t cell = global / (cellSize - 1);
      |                                   ^
/home/elsid/dev/openmw/components/esmterrain/storage.cpp:244:13: note: Assuming 'lodLevel' is >= 0
  244 |         if (lodLevel < 0 || 63 < lodLevel)
      |             ^~~~~~~~~~~~
/home/elsid/dev/openmw/components/esmterrain/storage.cpp:244:13: note: Left side of '||' is false
/home/elsid/dev/openmw/components/esmterrain/storage.cpp:244:29: note: Assuming 'lodLevel' is <= 63
  244 |         if (lodLevel < 0 || 63 < lodLevel)
      |                             ^~~~~~~~~~~~~
/home/elsid/dev/openmw/components/esmterrain/storage.cpp:244:9: note: Taking false branch
  244 |         if (lodLevel < 0 || 63 < lodLevel)
      |         ^
/home/elsid/dev/openmw/components/esmterrain/storage.cpp:247:13: note: Assuming 'size' is > 0
  247 |         if (size <= 0)
      |             ^~~~~~~~~
/home/elsid/dev/openmw/components/esmterrain/storage.cpp:247:9: note: Taking false branch
  247 |         if (size <= 0)
      |         ^
/home/elsid/dev/openmw/components/esmterrain/storage.cpp:272:13: note: Assuming the condition is false
  272 |         if (land != nullptr)
      |             ^~~~~~~~~~~~~~~
/home/elsid/dev/openmw/components/esmterrain/storage.cpp:272:9: note: Taking false branch
  272 |         if (land != nullptr)
      |         ^
/home/elsid/dev/openmw/components/esmterrain/storage.cpp:363:9: note: Calling 'sampleCellGrid<const (lambda at /home/elsid/dev/openmw/components/esmterrain/storage.cpp:280:35) &>'
  363 |         sampleCellGrid(cellSize, sampleSize, beginX, beginY, distance, handleSample);
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:72:13: note: Assuming 'cellSize' is >= 2
   72 |         if (cellSize < 2 || !Misc::isPowerOfTwo(cellSize - 1))
      |             ^~~~~~~~~~~~
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:72:13: note: Left side of '||' is false
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:72:9: note: Taking false branch
   72 |         if (cellSize < 2 || !Misc::isPowerOfTwo(cellSize - 1))
      |         ^
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:75:13: note: Assuming 'sampleSize' is not equal to 0
   75 |         if (sampleSize == 0 || !Misc::isPowerOfTwo(sampleSize))
      |             ^~~~~~~~~~~~~~~
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:75:13: note: Left side of '||' is false
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:75:9: note: Taking false branch
   75 |         if (sampleSize == 0 || !Misc::isPowerOfTwo(sampleSize))
      |         ^
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:78:13: note: Assuming 'distance' is >= 2
   78 |         if (distance < 2 || !Misc::isPowerOfTwo(distance - 1))
      |             ^~~~~~~~~~~~
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:78:13: note: Left side of '||' is false
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:78:9: note: Taking false branch
   78 |         if (distance < 2 || !Misc::isPowerOfTwo(distance - 1))
      |         ^
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:84:13: note: Assuming 'distance' is >= 'cellSize'
   84 |         if (distance < cellSize || sampleSize > cellSize - 1)
      |             ^~~~~~~~~~~~~~~~~~~
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:84:13: note: Left side of '||' is false
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:84:36: note: Assuming the condition is true
   84 |         if (distance < cellSize || sampleSize > cellSize - 1)
      |                                    ^~~~~~~~~~~~~~~~~~~~~~~~~
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:84:9: note: Taking true branch
   84 |         if (distance < cellSize || sampleSize > cellSize - 1)
      |         ^
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:85:20: note: Calling 'sampleCellGridSimple<const (lambda at /home/elsid/dev/openmw/components/esmterrain/storage.cpp:280:35) &>'
   85 |             return sampleCellGridSimple(cellSize, sampleSize, beginX, beginY, endX, endY, f);
      |                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:56:16: note: 'cellSize' is > 1
   56 |         assert(cellSize > 1);
      |                ^
/usr/include/assert.h💯27: note: expanded from macro 'assert'
  100 |      (static_cast <bool> (expr)                                         \
      |                           ^~~~
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:56:9: note: '?' condition is true
   56 |         assert(cellSize > 1);
      |         ^
/usr/include/assert.h💯7: note: expanded from macro 'assert'
  100 |      (static_cast <bool> (expr)                                         \
      |       ^
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:57:9: note: '?' condition is true
   57 |         assert(Misc::isPowerOfTwo(cellSize - 1));
      |         ^
/usr/include/assert.h💯7: note: expanded from macro 'assert'
  100 |      (static_cast <bool> (expr)                                         \
      |       ^
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:58:16: note: 'sampleSize' is not equal to 0
   58 |         assert(sampleSize != 0);
      |                ^
/usr/include/assert.h💯27: note: expanded from macro 'assert'
  100 |      (static_cast <bool> (expr)                                         \
      |                           ^~~~
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:58:9: note: '?' condition is true
   58 |         assert(sampleSize != 0);
      |         ^
/usr/include/assert.h💯7: note: expanded from macro 'assert'
  100 |      (static_cast <bool> (expr)                                         \
      |       ^
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:60:9: note: Calling 'sampleGrid<(lambda at /home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:61:13)>'
   60 |         sampleGrid(sampleSize, beginX, beginY, endX, endY,
      |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   61 |             [&](std::size_t globalX, std::size_t globalY, std::size_t vertX, std::size_t vertY) {
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   62 |                 const auto [cellX, x] = toCellAndLocal(beginX, globalX, cellSize);
      |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   63 |                 const auto [cellY, y] = toCellAndLocal(beginY, globalY, cellSize);
      |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   64 |                 f(cellX, cellY, x, y, vertX, vertY);
      |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   65 |             });
      |             ~~
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:33:38: note: Assuming 'y' is < 'endY'
   33 |         for (std::size_t y = beginY; y < endY; y += sampleSize)
      |                                      ^~~~~~~~
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:33:9: note: Loop condition is true.  Entering loop body
   33 |         for (std::size_t y = beginY; y < endY; y += sampleSize)
      |         ^
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:36:42: note: Assuming 'x' is < 'endX'
   36 |             for (std::size_t x = beginX; x < endX; x += sampleSize)
      |                                          ^~~~~~~~
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:36:13: note: Loop condition is true.  Entering loop body
   36 |             for (std::size_t x = beginX; x < endX; x += sampleSize)
      |             ^
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:36:42: note: Assuming 'x' is < 'endX'
   36 |             for (std::size_t x = beginX; x < endX; x += sampleSize)
      |                                          ^~~~~~~~
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:36:13: note: Loop condition is true.  Entering loop body
   36 |             for (std::size_t x = beginX; x < endX; x += sampleSize)
      |             ^
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:37:17: note: Calling 'operator()'
   37 |                 f(x, y, vertX++, vertY);
      |                 ^~~~~~~~~~~~~~~~~~~~~~~
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:62:41: note: Calling 'toCellAndLocal'
   62 |                 const auto [cellX, x] = toCellAndLocal(beginX, globalX, cellSize);
      |                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/elsid/dev/openmw/components/esmterrain/gridsampling.hpp:18:35: note: The result of the '/' expression is undefined
   18 |         std::size_t cell = global / (cellSize - 1);
      |                            ~~~~~~~^~~~~~~~~~~~~~~~
		
	
			
		
			
				
	
	
		
			208 lines
		
	
	
	
		
			7.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			208 lines
		
	
	
	
		
			7.8 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#ifndef OPENMW_COMPONENTS_ESMTERRAIN_GRIDSAMPLING_H
 | 
						|
#define OPENMW_COMPONENTS_ESMTERRAIN_GRIDSAMPLING_H
 | 
						|
 | 
						|
#include <components/misc/mathutil.hpp>
 | 
						|
 | 
						|
#include <cassert>
 | 
						|
#include <cmath>
 | 
						|
#include <cstddef>
 | 
						|
#include <stdexcept>
 | 
						|
#include <string>
 | 
						|
#include <utility>
 | 
						|
 | 
						|
namespace ESMTerrain
 | 
						|
{
 | 
						|
    inline std::pair<std::size_t, std::size_t> toCellAndLocal(
 | 
						|
        std::size_t begin, std::size_t global, std::size_t cellSize)
 | 
						|
    {
 | 
						|
        // NOLINTBEGIN(clang-analyzer-core.UndefinedBinaryOperatorResult)
 | 
						|
        std::size_t cell = global / (cellSize - 1);
 | 
						|
        // NOLINTEND(clang-analyzer-core.UndefinedBinaryOperatorResult)
 | 
						|
        std::size_t local = global & (cellSize - 2);
 | 
						|
        if (global != begin && local == 0)
 | 
						|
        {
 | 
						|
            --cell;
 | 
						|
            local = cellSize - 1;
 | 
						|
        }
 | 
						|
        return { cell, local };
 | 
						|
    }
 | 
						|
 | 
						|
    template <class F>
 | 
						|
    void sampleGrid(
 | 
						|
        std::size_t sampleSize, std::size_t beginX, std::size_t beginY, std::size_t endX, std::size_t endY, F&& f)
 | 
						|
    {
 | 
						|
        std::size_t vertY = 0;
 | 
						|
        for (std::size_t y = beginY; y < endY; y += sampleSize)
 | 
						|
        {
 | 
						|
            std::size_t vertX = 0;
 | 
						|
            for (std::size_t x = beginX; x < endX; x += sampleSize)
 | 
						|
                f(x, y, vertX++, vertY);
 | 
						|
            ++vertY;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    struct CellSample
 | 
						|
    {
 | 
						|
        int mCellX;
 | 
						|
        int mCellY;
 | 
						|
        std::size_t mSrcRow;
 | 
						|
        std::size_t mSrcCol;
 | 
						|
        std::size_t mDstRow;
 | 
						|
        std::size_t mDstCol;
 | 
						|
    };
 | 
						|
 | 
						|
    template <class F>
 | 
						|
    void sampleCellGridSimple(std::size_t cellSize, std::size_t sampleSize, std::size_t beginX, std::size_t beginY,
 | 
						|
        std::size_t endX, std::size_t endY, F&& f)
 | 
						|
    {
 | 
						|
        assert(cellSize > 1);
 | 
						|
        assert(Misc::isPowerOfTwo(cellSize - 1));
 | 
						|
        assert(sampleSize != 0);
 | 
						|
 | 
						|
        sampleGrid(sampleSize, beginX, beginY, endX, endY,
 | 
						|
            [&](std::size_t globalX, std::size_t globalY, std::size_t vertX, std::size_t vertY) {
 | 
						|
                const auto [cellX, x] = toCellAndLocal(beginX, globalX, cellSize);
 | 
						|
                const auto [cellY, y] = toCellAndLocal(beginY, globalY, cellSize);
 | 
						|
                f(cellX, cellY, x, y, vertX, vertY);
 | 
						|
            });
 | 
						|
    }
 | 
						|
 | 
						|
    template <class F>
 | 
						|
    void sampleCellGrid(std::size_t cellSize, std::size_t sampleSize, std::size_t beginX, std::size_t beginY,
 | 
						|
        std::size_t distance, F&& f)
 | 
						|
    {
 | 
						|
        if (cellSize < 2 || !Misc::isPowerOfTwo(cellSize - 1))
 | 
						|
            throw std::invalid_argument("Invalid cell size for cell grid sampling: " + std::to_string(cellSize));
 | 
						|
 | 
						|
        if (sampleSize == 0 || !Misc::isPowerOfTwo(sampleSize))
 | 
						|
            throw std::invalid_argument("Invalid sample size for cell grid sampling: " + std::to_string(sampleSize));
 | 
						|
 | 
						|
        if (distance < 2 || !Misc::isPowerOfTwo(distance - 1))
 | 
						|
            throw std::invalid_argument("Invalid count for cell grid sampling: " + std::to_string(distance));
 | 
						|
 | 
						|
        const std::size_t endX = beginX + distance;
 | 
						|
        const std::size_t endY = beginY + distance;
 | 
						|
 | 
						|
        if (distance < cellSize || sampleSize > cellSize - 1)
 | 
						|
            return sampleCellGridSimple(cellSize, sampleSize, beginX, beginY, endX, endY, f);
 | 
						|
 | 
						|
        const std::size_t beginCellX = beginX / (cellSize - 1);
 | 
						|
        const std::size_t beginCellY = beginY / (cellSize - 1);
 | 
						|
        const std::size_t endCellX = endX / (cellSize - 1);
 | 
						|
        const std::size_t endCellY = endY / (cellSize - 1);
 | 
						|
 | 
						|
        std::size_t baseVertY = 0;
 | 
						|
 | 
						|
        for (std::size_t cellY = beginCellY; cellY < endCellY; ++cellY)
 | 
						|
        {
 | 
						|
            const std::size_t offsetY = cellY * (cellSize - 1);
 | 
						|
            const std::size_t globalBeginY = offsetY <= beginY ? beginY : offsetY + sampleSize;
 | 
						|
            const std::size_t globalEndY = endY <= offsetY + cellSize ? endY : offsetY + cellSize;
 | 
						|
 | 
						|
            assert(globalBeginY < globalEndY);
 | 
						|
 | 
						|
            std::size_t baseVertX = 0;
 | 
						|
            std::size_t vertY = baseVertY;
 | 
						|
 | 
						|
            for (std::size_t cellX = beginCellX; cellX < endCellX; ++cellX)
 | 
						|
            {
 | 
						|
                const std::size_t offsetX = cellX * (cellSize - 1);
 | 
						|
                const std::size_t globalBeginX = offsetX <= beginX ? beginX : offsetX + sampleSize;
 | 
						|
                const std::size_t globalEndX = endX <= offsetX + cellSize ? endX : offsetX + cellSize;
 | 
						|
 | 
						|
                assert(globalBeginX < globalEndX);
 | 
						|
 | 
						|
                vertY = baseVertY;
 | 
						|
                std::size_t vertX = baseVertX;
 | 
						|
 | 
						|
                sampleGrid(sampleSize, globalBeginX, globalBeginY, globalEndX, globalEndY,
 | 
						|
                    [&](std::size_t globalX, std::size_t globalY, std::size_t localVertX, std::size_t localVertY) {
 | 
						|
                        vertX = baseVertX + localVertX;
 | 
						|
                        vertY = baseVertY + localVertY;
 | 
						|
                        f(cellX, cellY, globalX - offsetX, globalY - offsetY, vertX, vertY);
 | 
						|
                    });
 | 
						|
 | 
						|
                baseVertX = vertX + 1;
 | 
						|
            }
 | 
						|
 | 
						|
            baseVertY = vertY + 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    inline int getBlendmapSize(float size, int textureSize)
 | 
						|
    {
 | 
						|
        return static_cast<int>(textureSize * size) + 1;
 | 
						|
    }
 | 
						|
 | 
						|
    inline std::pair<std::size_t, std::size_t> getBlendmapLocalRange(
 | 
						|
        int cell, int minCell, int textureSize, int min, int max)
 | 
						|
    {
 | 
						|
        const int cellMin = (cell - minCell) * textureSize;
 | 
						|
        const int cellMax = cellMin + textureSize - 1;
 | 
						|
        const std::size_t begin = min > cellMin ? min - cellMin : 0;
 | 
						|
        const std::size_t end = cellMax < max ? textureSize : max - cellMin + 1;
 | 
						|
        assert(begin < end);
 | 
						|
        assert(static_cast<int>(end) <= textureSize);
 | 
						|
        return { begin, end };
 | 
						|
    }
 | 
						|
 | 
						|
    template <class F>
 | 
						|
    void sampleBlendmaps(float size, float minX, float minY, int textureSize, F&& f)
 | 
						|
    {
 | 
						|
        if (size <= 0)
 | 
						|
            throw std::invalid_argument("Invalid size for blendmap sampling: " + std::to_string(size));
 | 
						|
 | 
						|
        if (textureSize <= 0)
 | 
						|
            throw std::invalid_argument("Invalid texture size for blendmap sampling: " + std::to_string(textureSize));
 | 
						|
 | 
						|
        int minCellX = static_cast<int>(std::floor(minX));
 | 
						|
        const int minCellY = static_cast<int>(std::floor(minY));
 | 
						|
        int minRow = static_cast<int>((minX - minCellX) * (textureSize + 1)) - 1;
 | 
						|
        const int minCol = static_cast<int>((minY - minCellY) * (textureSize + 1));
 | 
						|
 | 
						|
        if (minRow < 0)
 | 
						|
        {
 | 
						|
            --minCellX;
 | 
						|
            minRow += textureSize;
 | 
						|
        }
 | 
						|
 | 
						|
        const int maxRow = minRow + static_cast<int>(textureSize * size);
 | 
						|
        const int maxCol = minCol + static_cast<int>(textureSize * size);
 | 
						|
        const int maxCellX = minCellX + maxRow / textureSize;
 | 
						|
        const int maxCellY = minCellY + maxCol / textureSize;
 | 
						|
 | 
						|
        std::size_t baseDstCol = 0;
 | 
						|
        for (int cellY = minCellY; cellY <= maxCellY; ++cellY)
 | 
						|
        {
 | 
						|
            std::size_t baseDstRow = 0;
 | 
						|
 | 
						|
            const auto [localBeginCol, localEndCol]
 | 
						|
                = getBlendmapLocalRange(cellY, minCellY, textureSize, minCol, maxCol);
 | 
						|
            const std::size_t colCount = localEndCol - localBeginCol;
 | 
						|
 | 
						|
            for (int cellX = minCellX; cellX <= maxCellX; ++cellX)
 | 
						|
            {
 | 
						|
                const auto [localBeginRow, localEndRow]
 | 
						|
                    = getBlendmapLocalRange(cellX, minCellX, textureSize, minRow, maxRow);
 | 
						|
                const std::size_t rowCount = localEndRow - localBeginRow;
 | 
						|
 | 
						|
                for (std::size_t col = 0; col < colCount; ++col)
 | 
						|
                    for (std::size_t row = 0; row < rowCount; ++row)
 | 
						|
                        f(CellSample{
 | 
						|
                            .mCellX = cellX,
 | 
						|
                            .mCellY = cellY,
 | 
						|
                            .mSrcRow = localBeginRow + row,
 | 
						|
                            .mSrcCol = localBeginCol + col,
 | 
						|
                            .mDstRow = baseDstRow + row,
 | 
						|
                            .mDstCol = baseDstCol + col,
 | 
						|
                        });
 | 
						|
 | 
						|
                baseDstRow += rowCount;
 | 
						|
            }
 | 
						|
 | 
						|
            baseDstCol += colCount;
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#endif
 |