File: Segment.h

package info (click to toggle)
mercator 0.3.0-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 2,008 kB
  • sloc: sh: 10,433; cpp: 4,482; makefile: 115
file content (223 lines) | stat: -rw-r--r-- 6,584 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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
// This file may be redistributed and modified only under the terms of
// the GNU General Public License (See COPYING for details).
// Copyright (C) 2003 Alistair Riddoch, Damien McGinnes

#ifndef MERCATOR_SEGMENT_H
#define MERCATOR_SEGMENT_H

#include <Mercator/Mercator.h>
#include <Mercator/Matrix.h>
#include <Mercator/BasePoint.h>

#include <wfmath/vector.h>
#include <wfmath/axisbox.h>

#include <set>
#include <map>

namespace WFMath {
class MTRand;
}

namespace Mercator {

class Terrain;
class Surface;
class TerrainMod;
typedef std::set<const TerrainMod *> ModList;
class Area;

// This class will need to be reference counted if we want the code to
// be able to hold onto it, as currently they get deleted internally
// whenever height points are asserted.

/// \brief Class storing heightfield and other data for a single fixed size
/// square area of terrain defined by four adjacent BasePoint objects.
class Segment {
  public:
    /// STL map of pointers to Surface objects.
    typedef std::map<int, Surface *> Surfacestore;
    
    /// STL multimap of pointers to Area objects affecting this segment.
    typedef std::multimap<int, const Area *> Areastore;
  private:
    /// Distance between segments
    const int m_res;
    /// Size of segment, m_res + 1
    const int m_size;
    /// Global x reference of this segment
    const int m_xRef;
    /// Global y reference of this segment
    const int m_yRef;
    /// 2x2 matrix of points which control this segment
    Matrix<2, 2, BasePoint> m_controlPoints;
    /// Pointer to buffer containing height points
    float * m_points;
    /// Pointer to buffer containing normals for height points
    float * m_normals;
    /// Maximum height of any point in this segment
    float m_max;
    /// Minimum height of any point in this segment
    float m_min;

    /// Store of surfaces which can be rendered on this terrain
    Surfacestore m_surfaces;
    
    /// Areas which intersect this segment
    Areastore m_areas;

    /// \brief List of TerrainMod objects that are applied to this Segment.
    ModList m_modList;
  public:
    explicit Segment(int x, int y, unsigned int resolution);
    ~Segment();

    /// \brief Accessor for resolution of this segment.
    const int getResolution() const {
        return m_res;
    }

    /// \brief Accessor for array size of this segment.
    const int getSize() const {
        return m_size;
    }

    /// \brief Accessor for Global x reference of this segment
    const int getXRef() const {
        return m_xRef;
    }

    /// \brief Accessor for Global y reference of this segment
    const int getYRef() const {
        return m_yRef;
    }

    /// \brief Check whether this Segment contains valid point data.
    ///
    /// @return true if this Segment is valid, false otherwise.
    const bool isValid() const {
        return (m_points != 0);
    }

    /// \brief Set min and max height values for this Segment.
    ///
    /// This is used after construction to set the initial values, and
    /// should not be used after populate has been called.
    void setMinMax(float min, float max) {
        m_min = min;
        m_max = max;
    }

    void invalidate(bool points = true);

    /// \brief Set the BasePoint data for one of the four that define this
    /// Segment.
    ///
    /// @param x relative x coord of base point. Must be 0 or 1.
    /// @param y relative y coord of base point. Must be 0 or 1.
    /// @param bp BasePoint data to be used.
    void setCornerPoint(unsigned int x, unsigned int y, const BasePoint & bp) {
        m_controlPoints(x, y) = bp;
        invalidate();
    }
    
    /// \brief Accessor for 2D matrix of base points.
    const Matrix<2, 2, BasePoint> & getControlPoints() const {
        return m_controlPoints;
    }

    /// \brief Accessor for modifying 2D matrix of base points.
    Matrix<2, 2, BasePoint> & getControlPoints() {
        return m_controlPoints;
    }

    /// \brief Accessor for list of attached Surface objects.
    const Surfacestore & getSurfaces() const {
        return m_surfaces;
    }

    /// \brief Accessor for modifying list of attached Surface objects.
    Surfacestore & getSurfaces() {
        return m_surfaces;
    }

    /// \brief Accessor for buffer containing height points.
    const float * getPoints() const {
        return m_points;
    }

    /// \brief Accessor for write access to buffer containing height points.
    float * getPoints() {
        return m_points;
    }

    /// \brief Accessor for buffer containing surface normals.
    const float * getNormals() const {
        return m_normals;
    }

    /// \brief Accessor for write access to buffer containing surface normals.
    float * getNormals() {
        return m_normals;
    }

    /// \brief Get the height at a relative integer position in the Segment.
    float get(int x, int y) const {
        return m_points[y * (m_res + 1) + x];
    }

    void getHeightAndNormal(float x, float y, float &h, 
                    WFMath::Vector<3> &normal) const;
    bool clipToSegment(const WFMath::AxisBox<2> &bbox, int &lx, int &hx, int &ly, int &hy) const;


    void populate();
    void populateNormals();
    void populateSurfaces();

    /// \brief Accessor for the maximum height value in this Segment.
    float getMax() const { return m_max; }
    /// \brief Accessor for the minimum height value in this Segment.
    float getMin() const { return m_min; }

    /// \brief The 2d area covered by this segment
    WFMath::AxisBox<2> getRect() const;

    /// \brief The 3d box covered by this segment
    WFMath::AxisBox<3> getBox() const;

    int addMod(const TerrainMod *t);
    int updateMod(const TerrainMod *t);
    int removeMod(const TerrainMod *t);
    void clearMods();
    
    /// \brief Accessor for multimap of Area objects.
    const Areastore& getAreas() const
    { return m_areas; }

    const ModList& getMods() const
    { return m_modList; }
    
    int addArea(const Area* a);
    int updateArea(const Area* a);
    int removeArea(const Area* a);
  private:
    void checkMaxMin(float h);

    void fill1d(const BasePoint& l, const BasePoint &h, float *array) const;

    void fill2d(const BasePoint& p1, const BasePoint& p2, 
                const BasePoint& p3, const BasePoint& p4);

    float qRMD(WFMath::MTRand& rng, float nn, float fn, float ff, float nf,
               float roughness, float falloff, int depth) const;

    void applyMod(const TerrainMod *t);

    void invalidateSurfaces();

};

} // namespace Mercator

#endif // MERCATOR_SEGMENT_H