24
24
using namespace Qt3DRender ;
25
25
26
26
27
- static QByteArray createPlaneVertexData ( int res, const QByteArray &heights )
27
+ static QByteArray createPlaneVertexData ( int res, float skirtHeight, const QByteArray &heights )
28
28
{
29
29
Q_ASSERT ( res >= 2 );
30
30
Q_ASSERT ( heights.count () == res * res * ( int )sizeof ( float ) );
31
31
32
- const float *zBits = ( const float * ) heights.constData ();
32
+ const float *zData = ( const float * ) heights.constData ();
33
+ const float *zBits = zData;
33
34
34
- const int nVerts = res * res;
35
+ const int nVerts = ( res + 2 ) * ( res + 2 ) ;
35
36
36
37
// Populate a buffer with the interleaved per-vertex data with
37
38
// vec3 pos, vec2 texCoord, vec3 normal, vec4 tangent
@@ -51,26 +52,35 @@ static QByteArray createPlaneVertexData( int res, const QByteArray &heights )
51
52
const float dv = 1.0 / ( resolution.height () - 1 );
52
53
53
54
// Iterate over z
54
- for ( int j = 0 ; j < resolution.height (); ++j )
55
+ for ( int j = - 1 ; j <= resolution.height (); ++j )
55
56
{
56
- const float z = z0 + static_cast <float >( j ) * dz;
57
- const float v = static_cast <float >( j ) * dv;
57
+ int jBound = qBound ( 0 , j, resolution.height () - 1 );
58
+ const float z = z0 + static_cast <float >( jBound ) * dz;
59
+ const float v = static_cast <float >( jBound ) * dv;
58
60
59
61
// Iterate over x
60
- for ( int i = 0 ; i < resolution.width (); ++i )
62
+ for ( int i = - 1 ; i <= resolution.width (); ++i )
61
63
{
62
- const float x = x0 + static_cast <float >( i ) * dx;
63
- const float u = static_cast <float >( i ) * du;
64
+ int iBound = qBound ( 0 , i, resolution.width () - 1 );
65
+ const float x = x0 + static_cast <float >( iBound ) * dx;
66
+ const float u = static_cast <float >( iBound ) * du;
67
+
68
+ float height;
69
+ if ( i == iBound && j == jBound )
70
+ height = *zBits++;
71
+ else
72
+ height = zData[ jBound * resolution.width () + iBound ] - skirtHeight;
64
73
65
74
// position
66
75
*fptr++ = x;
67
- *fptr++ = *zBits++ ;
76
+ *fptr++ = height ;
68
77
*fptr++ = z;
69
78
70
79
// texture coordinates
71
80
*fptr++ = u;
72
81
*fptr++ = v;
73
82
83
+ // TODO: compute correct normals based on neighboring pixels
74
84
// normal
75
85
*fptr++ = 0 .0f ;
76
86
*fptr++ = 1 .0f ;
@@ -85,22 +95,25 @@ static QByteArray createPlaneVertexData( int res, const QByteArray &heights )
85
95
static QByteArray createPlaneIndexData ( int res )
86
96
{
87
97
QSize resolution ( res, res );
98
+ int numVerticesX = resolution.width () + 2 ;
99
+ int numVerticesZ = resolution.height () + 2 ;
100
+
88
101
// Create the index data. 2 triangles per rectangular face
89
- const int faces = 2 * ( resolution. width () - 1 ) * ( resolution. height () - 1 );
102
+ const int faces = 2 * ( numVerticesX - 1 ) * ( numVerticesZ - 1 );
90
103
const quint32 indices = 3 * faces;
91
104
Q_ASSERT ( indices < std::numeric_limits<quint32>::max () );
92
105
QByteArray indexBytes;
93
106
indexBytes.resize ( indices * sizeof ( quint32 ) );
94
107
quint32 *indexPtr = reinterpret_cast <quint32 *>( indexBytes.data () );
95
108
96
109
// Iterate over z
97
- for ( int j = 0 ; j < resolution. height () - 1 ; ++j )
110
+ for ( int j = 0 ; j < numVerticesZ - 1 ; ++j )
98
111
{
99
- const int rowStartIndex = j * resolution. width () ;
100
- const int nextRowStartIndex = ( j + 1 ) * resolution. width () ;
112
+ const int rowStartIndex = j * numVerticesX ;
113
+ const int nextRowStartIndex = ( j + 1 ) * numVerticesX ;
101
114
102
115
// Iterate over x
103
- for ( int i = 0 ; i < resolution. width () - 1 ; ++i )
116
+ for ( int i = 0 ; i < numVerticesX - 1 ; ++i )
104
117
{
105
118
// Split quad into two triangles
106
119
*indexPtr++ = rowStartIndex + i;
@@ -122,23 +135,25 @@ static QByteArray createPlaneIndexData( int res )
122
135
class PlaneVertexBufferFunctor : public QBufferDataGenerator
123
136
{
124
137
public:
125
- explicit PlaneVertexBufferFunctor ( int resolution, const QByteArray &heightMap )
138
+ explicit PlaneVertexBufferFunctor ( int resolution, float skirtHeight, const QByteArray &heightMap )
126
139
: mResolution( resolution )
140
+ , mSkirtHeight( skirtHeight )
127
141
, mHeightMap( heightMap )
128
142
{}
129
143
130
144
~PlaneVertexBufferFunctor () {}
131
145
132
146
QByteArray operator ()() final
133
147
{
134
- return createPlaneVertexData ( mResolution , mHeightMap );
148
+ return createPlaneVertexData ( mResolution , mSkirtHeight , mHeightMap );
135
149
}
136
150
137
151
bool operator ==( const QBufferDataGenerator &other ) const final
138
152
{
139
153
const PlaneVertexBufferFunctor *otherFunctor = functor_cast<PlaneVertexBufferFunctor>( &other );
140
154
if ( otherFunctor != nullptr )
141
155
return ( otherFunctor->mResolution == mResolution &&
156
+ otherFunctor->mSkirtHeight == mSkirtHeight &&
142
157
otherFunctor->mHeightMap == mHeightMap );
143
158
return false ;
144
159
}
@@ -147,6 +162,7 @@ class PlaneVertexBufferFunctor : public QBufferDataGenerator
147
162
148
163
private:
149
164
int mResolution ;
165
+ float mSkirtHeight ;
150
166
QByteArray mHeightMap ;
151
167
};
152
168
@@ -184,9 +200,10 @@ class PlaneIndexBufferFunctor : public QBufferDataGenerator
184
200
// ------------
185
201
186
202
187
- DemTerrainTileGeometry::DemTerrainTileGeometry ( int resolution, const QByteArray &heightMap, DemTerrainTileGeometry::QNode *parent )
203
+ DemTerrainTileGeometry::DemTerrainTileGeometry ( int resolution, float skirtHeight, const QByteArray &heightMap, DemTerrainTileGeometry::QNode *parent )
188
204
: QGeometry( parent )
189
205
, mResolution( resolution )
206
+ , mSkirtHeight( skirtHeight )
190
207
, mHeightMap( heightMap )
191
208
{
192
209
init ();
@@ -201,9 +218,11 @@ void DemTerrainTileGeometry::init()
201
218
mVertexBuffer = new Qt3DRender::QBuffer ( Qt3DRender::QBuffer::VertexBuffer, this );
202
219
mIndexBuffer = new Qt3DRender::QBuffer ( Qt3DRender::QBuffer::IndexBuffer, this );
203
220
204
- const int nVerts = mResolution * mResolution ;
221
+ int nVertsX = mResolution + 2 ;
222
+ int nVertsZ = mResolution + 2 ;
223
+ const int nVerts = nVertsX * nVertsZ;
205
224
const int stride = ( 3 + 2 + 3 ) * sizeof ( float );
206
- const int faces = 2 * ( mResolution - 1 ) * ( mResolution - 1 );
225
+ const int faces = 2 * ( nVertsX - 1 ) * ( nVertsZ - 1 );
207
226
208
227
mPositionAttribute ->setName ( QAttribute::defaultPositionAttributeName () );
209
228
mPositionAttribute ->setVertexBaseType ( QAttribute::Float );
@@ -238,7 +257,7 @@ void DemTerrainTileGeometry::init()
238
257
// Each primitive has 3 vertives
239
258
mIndexAttribute ->setCount ( faces * 3 );
240
259
241
- mVertexBuffer ->setDataGenerator ( QSharedPointer<PlaneVertexBufferFunctor>::create ( mResolution , mHeightMap ) );
260
+ mVertexBuffer ->setDataGenerator ( QSharedPointer<PlaneVertexBufferFunctor>::create ( mResolution , mSkirtHeight , mHeightMap ) );
242
261
mIndexBuffer ->setDataGenerator ( QSharedPointer<PlaneIndexBufferFunctor>::create ( mResolution ) );
243
262
244
263
addAttribute ( mPositionAttribute );
0 commit comments