QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgschunknode_p.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgschunknode_p.cpp
3 --------------------------------------
4 Date : July 2017
5 Copyright : (C) 2017 by Martin Dobias
6 Email : wonder dot sk at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgschunknode_p.h"
17
18#include "qgschunkedentity_p.h" // for ChunkLoader destructor
19#include "qgschunklist_p.h"
20#include "qgschunkloader_p.h"
21#include <Qt3DCore/QEntity>
22
24
25QgsChunkNode::QgsChunkNode( const QgsChunkNodeId &nodeId, const QgsAABB &bbox, float error, QgsChunkNode *parent )
26 : mBbox( bbox )
27 , mError( error )
28 , mNodeId( nodeId )
29 , mParent( parent )
30 , mState( Skeleton )
31 , mLoaderQueueEntry( nullptr )
32 , mReplacementQueueEntry( nullptr )
33 , mLoader( nullptr )
34 , mEntity( nullptr )
35 , mUpdaterFactory( nullptr )
36 , mUpdater( nullptr )
37{
38 // TODO: still using a fixed size array. Use QVector instead?
39 for ( int i = 0; i < 8; ++i )
40 mChildren[i] = nullptr;
41}
42
43QgsChunkNode::~QgsChunkNode()
44{
45 Q_ASSERT( mState == Skeleton );
46 Q_ASSERT( !mLoaderQueueEntry );
47 Q_ASSERT( !mReplacementQueueEntry );
48 Q_ASSERT( !mLoader ); // should be deleted when removed from loader queue
49 Q_ASSERT( !mEntity ); // should be deleted when removed from replacement queue
50 Q_ASSERT( !mUpdater );
51 Q_ASSERT( !mUpdaterFactory );
52
53 for ( int i = 0; i < childCount(); ++i )
54 delete mChildren[i];
55}
56
57bool QgsChunkNode::allChildChunksResident( QTime currentTime ) const
58{
59 Q_ASSERT( mChildCount != -1 );
60 for ( int i = 0; i < childCount(); ++i )
61 {
62 if ( !mChildren[i] )
63 return false; // not even a skeleton
64 if ( mChildren[i]->mHasData && !mChildren[i]->mEntity )
65 return false; // no there yet
66 Q_UNUSED( currentTime ) // seems we do not need this extra time (it just brings extra problems)
67 //if (children[i]->entityCreatedTime.msecsTo(currentTime) < 100)
68 // return false; // allow some time for upload of stuff within Qt3D (TODO: better way to check it is ready?)
69 }
70 return true;
71}
72
73void QgsChunkNode::populateChildren( const QVector<QgsChunkNode *> &children )
74{
75 Q_ASSERT( mChildCount == -1 );
76 mChildCount = children.count();
77 for ( int i = 0; i < mChildCount; ++i )
78 mChildren[i] = children[i];
79}
80
81int QgsChunkNode::level() const
82{
83 int lvl = 0;
84 QgsChunkNode *p = mParent;
85 while ( p )
86 {
87 ++lvl;
88 p = p->mParent;
89 }
90 return lvl;
91}
92
93QList<QgsChunkNode *> QgsChunkNode::descendants()
94{
95 QList<QgsChunkNode *> lst;
96 lst << this;
97
98 for ( int i = 0; i < childCount(); ++i )
99 {
100 if ( mChildren[i] )
101 lst << mChildren[i]->descendants();
102 }
103
104 return lst;
105}
106
107void QgsChunkNode::setQueuedForLoad( QgsChunkListEntry *entry )
108{
109 Q_ASSERT( mState == Skeleton );
110 Q_ASSERT( !mLoaderQueueEntry );
111 Q_ASSERT( !mLoader );
112
113 mState = QgsChunkNode::QueuedForLoad;
114 mLoaderQueueEntry = entry;
115}
116
117void QgsChunkNode::cancelQueuedForLoad()
118{
119 Q_ASSERT( mState == QueuedForLoad );
120 Q_ASSERT( mLoaderQueueEntry );
121
122 delete mLoaderQueueEntry;
123 mLoaderQueueEntry = nullptr;
124
125 mState = QgsChunkNode::Skeleton;
126}
127
128void QgsChunkNode::setLoading( QgsChunkLoader *chunkLoader )
129{
130 Q_ASSERT( mState == QueuedForLoad );
131 Q_ASSERT( !mLoader );
132 Q_ASSERT( mLoaderQueueEntry );
133
134 mState = Loading;
135 mLoader = chunkLoader;
136 mLoaderQueueEntry = nullptr;
137}
138
139void QgsChunkNode::cancelLoading()
140{
141 Q_ASSERT( mState == QgsChunkNode::Loading );
142 Q_ASSERT( mLoader );
143 Q_ASSERT( !mLoaderQueueEntry );
144 Q_ASSERT( !mEntity );
145 Q_ASSERT( !mReplacementQueueEntry );
146
147 mLoader = nullptr; // not owned by chunk node
148
149 mState = QgsChunkNode::Skeleton;
150}
151
152void QgsChunkNode::setLoaded( Qt3DCore::QEntity *newEntity )
153{
154 Q_ASSERT( mState == QgsChunkNode::Loading );
155 Q_ASSERT( mLoader );
156 Q_ASSERT( !mLoaderQueueEntry );
157 Q_ASSERT( !mReplacementQueueEntry );
158
159 mEntity = newEntity;
160 mEntityCreatedTime = QTime::currentTime();
161
162 mLoader = nullptr; // not owned by chunk node
163
164 mState = QgsChunkNode::Loaded;
165 mReplacementQueueEntry = new QgsChunkListEntry( this );
166}
167
168void QgsChunkNode::unloadChunk()
169{
170 Q_ASSERT( mState == QgsChunkNode::Loaded );
171 Q_ASSERT( mEntity );
172 Q_ASSERT( mReplacementQueueEntry );
173
174 delete mEntity;
175 mEntity = nullptr;
176
177 delete mReplacementQueueEntry;
178 mReplacementQueueEntry = nullptr;
179 mState = QgsChunkNode::Skeleton;
180}
181
182void QgsChunkNode::setQueuedForUpdate( QgsChunkListEntry *entry, QgsChunkQueueJobFactory *updateJobFactory )
183{
184 Q_ASSERT( mState == QgsChunkNode::Loaded );
185 Q_ASSERT( mEntity );
186 Q_ASSERT( mReplacementQueueEntry );
187 Q_ASSERT( !mLoaderQueueEntry );
188 Q_ASSERT( !mUpdater );
189 Q_ASSERT( !mUpdaterFactory );
190
191 mState = QueuedForUpdate;
192 mLoaderQueueEntry = entry;
193 mUpdaterFactory = updateJobFactory;
194}
195
196void QgsChunkNode::cancelQueuedForUpdate()
197{
198 Q_ASSERT( mState == QueuedForUpdate );
199 Q_ASSERT( mEntity );
200 Q_ASSERT( mLoaderQueueEntry );
201 Q_ASSERT( mUpdaterFactory );
202 Q_ASSERT( !mUpdater );
203
204 mState = Loaded;
205 mUpdaterFactory = nullptr; // not owned by the node
206
207 delete mLoaderQueueEntry;
208 mLoaderQueueEntry = nullptr;
209}
210
211void QgsChunkNode::setUpdating()
212{
213 Q_ASSERT( mState == QgsChunkNode::QueuedForUpdate );
214 Q_ASSERT( mEntity );
215 Q_ASSERT( mReplacementQueueEntry );
216 Q_ASSERT( mLoaderQueueEntry );
217 Q_ASSERT( !mUpdater );
218 Q_ASSERT( mUpdaterFactory );
219
220 mState = Updating;
221 mUpdater = mUpdaterFactory->createJob( this );
222 mUpdaterFactory = nullptr; // not owned by the node
223 mLoaderQueueEntry = nullptr;
224}
225
226void QgsChunkNode::cancelUpdating()
227{
228 Q_ASSERT( mState == QgsChunkNode::Updating );
229 Q_ASSERT( mUpdater );
230 Q_ASSERT( !mLoaderQueueEntry );
231
232 mUpdater = nullptr; // not owned by chunk node
233
234 mState = Loaded;
235}
236
237void QgsChunkNode::setUpdated()
238{
239 Q_ASSERT( mState == QgsChunkNode::Updating );
240 Q_ASSERT( mUpdater );
241 Q_ASSERT( !mLoaderQueueEntry );
242 Q_ASSERT( mReplacementQueueEntry );
243
244 mUpdater = nullptr; // not owned by chunk node
245
246 mState = QgsChunkNode::Loaded;
247}
248
249void QgsChunkNode::setExactBbox( const QgsAABB &box )
250{
251 mBbox = box;
252
253 // TODO: propagate better estimate to children?
254}
255
256void QgsChunkNode::updateParentBoundingBoxesRecursively() const
257{
258 QgsChunkNode *currentNode = parent();
259 while ( currentNode )
260 {
261 QgsChunkNode *const *currentNodeChildren = currentNode->children();
262 float xMin = std::numeric_limits< float >::max();
263 float xMax = -std::numeric_limits< float >::max();
264 float yMin = std::numeric_limits< float >::max();
265 float yMax = -std::numeric_limits< float >::max();
266 float zMin = std::numeric_limits< float >::max();
267 float zMax = -std::numeric_limits< float >::max();
268 for ( int i = 0; i < currentNode->childCount(); ++i )
269 {
270 const QgsAABB childBBox = currentNodeChildren[i]->bbox();
271 if ( childBBox.xMin < xMin )
272 xMin = childBBox.xMin;
273 if ( childBBox.yMin < yMin )
274 yMin = childBBox.yMin;
275 if ( childBBox.zMin < zMin )
276 zMin = childBBox.zMin;
277 if ( childBBox.xMax > xMax )
278 xMax = childBBox.xMax;
279 if ( childBBox.yMax > yMax )
280 yMax = childBBox.yMax;
281 if ( childBBox.zMax > zMax )
282 zMax = childBBox.zMax;
283 }
284 currentNode->setExactBbox( QgsAABB( xMin, yMin, zMin, xMax, yMax, zMax ) );
285 currentNode = currentNode->parent();
286 }
287}
288
3
Definition: qgsaabb.h:34
float yMax
Definition: qgsaabb.h:85
float xMax
Definition: qgsaabb.h:84
float xMin
Definition: qgsaabb.h:81
float zMax
Definition: qgsaabb.h:86
float yMin
Definition: qgsaabb.h:82
float zMin
Definition: qgsaabb.h:83