File: storage.hpp

package info (click to toggle)
openmw 0.49.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 33,992 kB
  • sloc: cpp: 372,479; xml: 2,149; sh: 1,403; python: 797; makefile: 26
file content (166 lines) | stat: -rw-r--r-- 6,854 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#ifndef OPENMW_COMPONENTS_ESMTERRAIN_STORAGE_H
#define OPENMW_COMPONENTS_ESMTERRAIN_STORAGE_H

#include <cassert>
#include <mutex>

#include <components/terrain/storage.hpp>

#include <components/esm/esmterrain.hpp>
#include <components/esm/exteriorcelllocation.hpp>
#include <components/esm3/loadltex.hpp>

namespace ESM4
{
    struct Land;
}

namespace ESM
{
    class LandData;
}

namespace VFS
{
    class Manager;
}

namespace ESMTerrain
{

    class LandCache;

    /// @brief Wrapper around Land Data with reference counting. The wrapper needs to be held as long as the data is
    /// still in use
    class LandObject : public osg::Object
    {
    public:
        LandObject() = default;
        LandObject(const ESM::Land& land, int loadFlags);
        LandObject(const ESM4::Land& land, int loadFlags);

        META_Object(ESMTerrain, LandObject)

        const ESM::LandData* getData(int flags) const
        {
            if ((mData.getLoadFlags() & flags) != flags)
                return nullptr;

            return &mData;
        }

        int getPlugin() const { return mData.getPlugin(); }

    private:
        ESM::LandData mData;

        LandObject(const LandObject& copy, const osg::CopyOp& copyOp);
    };

    // Since plugins can define new texture palettes, we need to know the plugin index too
    // in order to retrieve the correct texture name.
    // pair  <texture id, plugin id>
    using UniqueTextureId = std::pair<std::uint16_t, int>;

    /// @brief Feeds data from ESM terrain records (ESM::Land, ESM::LandTexture)
    ///        into the terrain component, converting it on the fly as needed.
    class Storage : public Terrain::Storage
    {
    public:
        Storage(const VFS::Manager* vfs, std::string_view normalMapPattern = {},
            std::string_view normalHeightMapPattern = {}, bool autoUseNormalMaps = false,
            std::string_view specularMapPattern = {}, bool autoUseSpecularMaps = false);

        // Not implemented in this class, because we need different Store implementations for game and editor
        virtual osg::ref_ptr<const LandObject> getLand(ESM::ExteriorCellLocation cellLocation) = 0;
        virtual const std::string* getLandTexture(std::uint16_t index, int plugin) = 0;
        /// Get bounds of the whole terrain in cell units
        void getBounds(float& minX, float& maxX, float& minY, float& maxY, ESM::RefId worldspace) override = 0;

        /// Get the minimum and maximum heights of a terrain region.
        /// @note Will only be called for chunks with size = minBatchSize, i.e. leafs of the quad tree.
        ///        Larger chunks can simply merge AABB of children.
        /// @param size size of the chunk in cell units
        /// @param center center of the chunk in cell units
        /// @param min min height will be stored here
        /// @param max max height will be stored here
        /// @return true if there was data available for this terrain chunk
        bool getMinMaxHeights(
            float size, const osg::Vec2f& center, ESM::RefId worldspace, float& min, float& max) override;

        /// Fill vertex buffers for a terrain chunk.
        /// @note May be called from background threads. Make sure to only call thread-safe functions from here!
        /// @note Vertices should be written in row-major order (a row is defined as parallel to the x-axis).
        ///       The specified positions should be in local space, i.e. relative to the center of the terrain chunk.
        /// @param lodLevel LOD level, 0 = most detailed
        /// @param size size of the terrain chunk in cell units
        /// @param center center of the chunk in cell units
        /// @param positions buffer to write vertices
        /// @param normals buffer to write vertex normals
        /// @param colours buffer to write vertex colours
        void fillVertexBuffers(int lodLevel, float size, const osg::Vec2f& center, ESM::RefId worldspace,
            osg::Vec3Array& positions, osg::Vec3Array& normals, osg::Vec4ubArray& colours) override;

        /// Create textures holding layer blend values for a terrain chunk.
        /// @note The terrain chunk shouldn't be larger than one cell since otherwise we might
        ///       have to do a ridiculous amount of different layers. For larger chunks, composite maps should be used.
        /// @note May be called from background threads.
        /// @param chunkSize size of the terrain chunk in cell units
        /// @param chunkCenter center of the chunk in cell units
        /// @param blendmaps created blendmaps will be written here
        /// @param layerList names of the layer textures used will be written here
        void getBlendmaps(float chunkSize, const osg::Vec2f& chunkCenter, ImageVector& blendmaps,
            std::vector<Terrain::LayerInfo>& layerList, ESM::RefId worldspace) override;

        float getHeightAt(const osg::Vec3f& worldPos, ESM::RefId worldspace) override;

        /// Get the transformation factor for mapping cell units to world units.
        float getCellWorldSize(ESM::RefId worldspace) override;

        /// Get the number of vertices on one side for each cell. Should be (power of two)+1
        int getCellVertices(ESM::RefId worldspace) override;

        int getBlendmapScale(float chunkSize) override;

        float getVertexHeight(const ESM::LandData* data, int x, int y)
        {
            const int landSize = data->getLandSize();
            assert(x < landSize);
            assert(y < landSize);
            return data->getHeights()[y * landSize + x];
        }

    private:
        const VFS::Manager* mVFS;

        inline void fixNormal(
            osg::Vec3f& normal, ESM::ExteriorCellLocation cellLocation, int col, int row, LandCache& cache);
        inline void fixColour(
            osg::Vec4ub& colour, ESM::ExteriorCellLocation cellLocation, int col, int row, LandCache& cache);
        inline void averageNormal(
            osg::Vec3f& normal, ESM::ExteriorCellLocation cellLocation, int col, int row, LandCache& cache);

        inline const LandObject* getLand(ESM::ExteriorCellLocation cellLocation, LandCache& cache);

        virtual bool useAlteration() const { return false; }
        virtual void adjustColor(int col, int row, const ESM::LandData* heightData, osg::Vec4ub& color) const;
        virtual float getAlteredHeight(int col, int row) const;

        std::string getTextureName(UniqueTextureId id);

        std::map<std::string, Terrain::LayerInfo> mLayerInfoMap;
        std::mutex mLayerInfoMutex;

        std::string mNormalMapPattern;
        std::string mNormalHeightMapPattern;
        bool mAutoUseNormalMaps;

        std::string mSpecularMapPattern;
        bool mAutoUseSpecularMaps;

        Terrain::LayerInfo getLayerInfo(const std::string& texture);
    };

}

#endif