x.patch 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481
  1. If an entity uses a QBoundingVolume and a QGeometryView, compute
  2. the bounding volume data in the core aspect. All other cases will
  3. still happen in the render aspect.
  4. Result not currently used (ie it's done again in render aspect).
  5. Change-Id: I4b5ed21bac42b79777c3112aa76d876ac5b6f52d
  6. Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
  7. 14 files changed:
  8. src/core/aspect/qcoreaspect.cpp patch | blob | history
  9. src/core/aspect/qcoreaspect.h patch | blob | history
  10. src/core/aspect/qcoreaspect_p.h patch | blob | history
  11. src/core/core.pro patch | blob | history
  12. src/core/geometry/bufferutils_p.h [new file with mode: 0644] patch | blob
  13. src/core/geometry/buffervisitor_p.h [new file with mode: 0644] patch | blob
  14. src/core/geometry/geometry.pri patch | blob | history
  15. src/core/geometry/qgeometry_p.h patch | blob | history
  16. src/core/geometry/qgeometryview.cpp patch | blob | history
  17. src/core/geometry/qgeometryview_p.h patch | blob | history
  18. src/core/jobs/calcboundingvolumejob.cpp [new file with mode: 0644] patch | blob
  19. src/core/jobs/calcboundingvolumejob_p.h [new file with mode: 0644] patch | blob
  20. src/core/jobs/job_common_p.h [new file with mode: 0644] patch | blob
  21. src/core/jobs/jobs.pri patch | blob | history
  22. diff --git a/src/core/aspect/qcoreaspect.cpp b/src/core/aspect/qcoreaspect.cpp
  23. index 48f9aaf..dc3566e 100644 (file)
  24. --- a/src/core/aspect/qcoreaspect.cpp
  25. +++ b/src/core/aspect/qcoreaspect.cpp
  26. @@ -39,12 +39,16 @@
  27. #include "qcoreaspect.h"
  28. #include "qcoreaspect_p.h"
  29. +#include <Qt3DCore/private/qaspectmanager_p.h>
  30. +#include <Qt3DCore/private/qscene_p.h>
  31. +#include <Qt3DCore/private/calcboundingvolumejob_p.h>
  32. QT_BEGIN_NAMESPACE
  33. using namespace Qt3DCore;
  34. QCoreAspectPrivate::QCoreAspectPrivate()
  35. + : Qt3DCore::QAbstractAspectPrivate()
  36. {
  37. }
  38. @@ -65,7 +69,7 @@ void QCoreAspectPrivate::frameDone()
  39. }
  40. QCoreAspect::QCoreAspect(QObject *parent)
  41. - : Qt3DCore::QAbstractAspect(parent)
  42. + : Qt3DCore::QAbstractAspect(*new QCoreAspectPrivate, parent)
  43. {
  44. }
  45. @@ -75,10 +79,28 @@ QCoreAspect::~QCoreAspect()
  46. }
  47. +QAspectJobPtr QCoreAspect::calculateBoundingVolumeJob() const
  48. +{
  49. + Q_D(const QCoreAspect);
  50. + return d->m_calculateBoundingVolumeJob;
  51. +}
  52. +
  53. QVector<QAspectJobPtr> QCoreAspect::jobsToExecute(qint64 time)
  54. {
  55. + Q_D(QCoreAspect);
  56. Q_UNUSED(time)
  57. - return {};
  58. +
  59. + QVector<QAspectJobPtr> jobs;
  60. +
  61. + auto scene = d->m_aspectManager->scene();
  62. + auto dirtyBits = scene->dirtyBits();
  63. +
  64. + if (dirtyBits & QScene::GeometryDirty ||
  65. + dirtyBits & QScene::BuffersDirty) {
  66. + jobs.push_back(d->m_calculateBoundingVolumeJob);
  67. + }
  68. +
  69. + return jobs;
  70. }
  71. QVariant QCoreAspect::executeCommand(const QStringList &args)
  72. @@ -89,12 +111,25 @@ QVariant QCoreAspect::executeCommand(const QStringList &args)
  73. void QCoreAspect::onRegistered()
  74. {
  75. + Q_D(QCoreAspect);
  76. + if (d->m_calculateBoundingVolumeJob.isNull())
  77. + d->m_calculateBoundingVolumeJob = CalculateBoundingVolumeJobPtr::create();
  78. }
  79. -void QCoreAspect::onUnregistered()
  80. +void QCoreAspect::onEngineStartup()
  81. {
  82. + Q_D(QCoreAspect);
  83. + Q_ASSERT(d->m_calculateBoundingVolumeJob);
  84. + d->m_calculateBoundingVolumeJob->setRoot(d->m_root);
  85. +}
  86. +
  87. +void QCoreAspect::frameDone()
  88. +{
  89. + Q_D(QCoreAspect);
  90. + auto scene = d->m_aspectManager->scene();
  91. + scene->clearDirtyBits();
  92. }
  93. QT_END_NAMESPACE
  94. diff --git a/src/core/aspect/qcoreaspect.h b/src/core/aspect/qcoreaspect.h
  95. index 27c72f4..071b738 100644 (file)
  96. --- a/src/core/aspect/qcoreaspect.h
  97. +++ b/src/core/aspect/qcoreaspect.h
  98. @@ -55,6 +55,8 @@ public:
  99. explicit QCoreAspect(QObject *parent = nullptr);
  100. ~QCoreAspect();
  101. + QAspectJobPtr calculateBoundingVolumeJob() const;
  102. +
  103. protected:
  104. Q_DECLARE_PRIVATE(QCoreAspect)
  105. @@ -62,7 +64,8 @@ private:
  106. QVector<Qt3DCore::QAspectJobPtr> jobsToExecute(qint64 time) override;
  107. QVariant executeCommand(const QStringList &args) override;
  108. void onRegistered() override;
  109. - void onUnregistered() override;
  110. + void onEngineStartup() override;
  111. + void frameDone() override;
  112. };
  113. }
  114. diff --git a/src/core/aspect/qcoreaspect_p.h b/src/core/aspect/qcoreaspect_p.h
  115. index ca665fa..cda0a14 100644 (file)
  116. --- a/src/core/aspect/qcoreaspect_p.h
  117. +++ b/src/core/aspect/qcoreaspect_p.h
  118. @@ -55,10 +55,15 @@
  119. #include <Qt3DCore/private/qabstractaspect_p.h>
  120. #include <Qt3DCore/private/qt3dcore_global_p.h>
  121. +#include <QSharedPointer>
  122. +
  123. QT_BEGIN_NAMESPACE
  124. namespace Qt3DCore {
  125. +class CalculateBoundingVolumeJob;
  126. +using CalculateBoundingVolumeJobPtr = QSharedPointer<CalculateBoundingVolumeJob>;
  127. +
  128. class Q_3DCORE_PRIVATE_EXPORT QCoreAspectPrivate : public Qt3DCore::QAbstractAspectPrivate
  129. {
  130. public:
  131. @@ -71,6 +76,7 @@ public:
  132. void frameDone() override;
  133. bool m_initialized;
  134. + CalculateBoundingVolumeJobPtr m_calculateBoundingVolumeJob;
  135. };
  136. }
  137. diff --git a/src/core/core.pro b/src/core/core.pro
  138. index b149497..846e9d8 100644 (file)
  139. --- a/src/core/core.pro
  140. +++ b/src/core/core.pro
  141. @@ -1,7 +1,8 @@
  142. -TARGET = Qt3DCore
  143. -MODULE = 3dcore
  144. +TARGET = Qt3DCore
  145. +MODULE = 3dcore
  146. -QT = core-private gui-private network
  147. +QT = core-private gui-private network
  148. +QT_FOR_PRIVATE = concurrent
  149. gcov {
  150. QMAKE_CXXFLAGS += -fprofile-arcs -ftest-coverage
  151. diff --git a/src/core/geometry/bufferutils_p.h b/src/core/geometry/bufferutils_p.h
  152. new file mode 100644 (file)
  153. index 0000000..1b83d99
  154. --- /dev/null
  155. +++ b/src/core/geometry/bufferutils_p.h
  156. @@ -0,0 +1,113 @@
  157. +/****************************************************************************
  158. +**
  159. +** Copyright (C) 2015 Paul Lemire paul.lemire350@gmail.com
  160. +** Contact: https://www.qt.io/licensing/
  161. +**
  162. +** This file is part of the Qt3D module of the Qt Toolkit.
  163. +**
  164. +** $QT_BEGIN_LICENSE:LGPL$
  165. +** Commercial License Usage
  166. +** Licensees holding valid commercial Qt licenses may use this file in
  167. +** accordance with the commercial license agreement provided with the
  168. +** Software or, alternatively, in accordance with the terms contained in
  169. +** a written agreement between you and The Qt Company. For licensing terms
  170. +** and conditions see https://www.qt.io/terms-conditions. For further
  171. +** information use the contact form at https://www.qt.io/contact-us.
  172. +**
  173. +** GNU Lesser General Public License Usage
  174. +** Alternatively, this file may be used under the terms of the GNU Lesser
  175. +** General Public License version 3 as published by the Free Software
  176. +** Foundation and appearing in the file LICENSE.LGPL3 included in the
  177. +** packaging of this file. Please review the following information to
  178. +** ensure the GNU Lesser General Public License version 3 requirements
  179. +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
  180. +**
  181. +** GNU General Public License Usage
  182. +** Alternatively, this file may be used under the terms of the GNU
  183. +** General Public License version 2.0 or (at your option) the GNU General
  184. +** Public license version 3 or any later version approved by the KDE Free
  185. +** Qt Foundation. The licenses are as published by the Free Software
  186. +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
  187. +** included in the packaging of this file. Please review the following
  188. +** information to ensure the GNU General Public License requirements will
  189. +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
  190. +** https://www.gnu.org/licenses/gpl-3.0.html.
  191. +**
  192. +** $QT_END_LICENSE$
  193. +**
  194. +****************************************************************************/
  195. +
  196. +#ifndef QT3DCORE_BUFFERUTILS_P_H
  197. +#define QT3DCORE_BUFFERUTILS_P_H
  198. +
  199. +//
  200. +// W A R N I N G
  201. +// -------------
  202. +//
  203. +// This file is not part of the Qt API. It exists for the convenience
  204. +// of other Qt classes. This header file may change from version to
  205. +// version without notice, or even be removed.
  206. +//
  207. +// We mean it.
  208. +//
  209. +
  210. +#include <Qt3DCore/QAttribute>
  211. +#include <QByteArray>
  212. +
  213. +QT_BEGIN_NAMESPACE
  214. +
  215. +
  216. +namespace Qt3DCore {
  217. +
  218. +class QGeometryView;
  219. +class QBuffer;
  220. +
  221. +struct BufferInfo
  222. +{
  223. + BufferInfo()
  224. + : type(Qt3DCore::QAttribute::VertexBaseType::Float)
  225. + , dataSize(0)
  226. + , count(0)
  227. + , byteStride(0)
  228. + , byteOffset(0)
  229. + , restartEnabled(false)
  230. + , restartIndexValue(-1)
  231. + {}
  232. +
  233. + QByteArray data;
  234. + Qt3DCore::QAttribute::VertexBaseType type;
  235. + uint dataSize;
  236. + uint count;
  237. + uint byteStride;
  238. + uint byteOffset;
  239. + bool restartEnabled;
  240. + int restartIndexValue;
  241. +};
  242. +
  243. +
  244. +namespace BufferTypeInfo {
  245. +
  246. + template <Qt3DCore::QAttribute::VertexBaseType> struct EnumToType;
  247. + template <> struct EnumToType<Qt3DCore::QAttribute::Byte> { typedef const char type; };
  248. + template <> struct EnumToType<Qt3DCore::QAttribute::UnsignedByte> { typedef const uchar type; };
  249. + template <> struct EnumToType<Qt3DCore::QAttribute::Short> { typedef const short type; };
  250. + template <> struct EnumToType<Qt3DCore::QAttribute::UnsignedShort> { typedef const ushort type; };
  251. + template <> struct EnumToType<Qt3DCore::QAttribute::Int> { typedef const int type; };
  252. + template <> struct EnumToType<Qt3DCore::QAttribute::UnsignedInt> { typedef const uint type; };
  253. + template <> struct EnumToType<Qt3DCore::QAttribute::Float> { typedef const float type; };
  254. + template <> struct EnumToType<Qt3DCore::QAttribute::Double> { typedef const double type; };
  255. +
  256. + template<Qt3DCore::QAttribute::VertexBaseType v>
  257. + typename EnumToType<v>::type *castToType(const QByteArray &u, uint byteOffset)
  258. + {
  259. + return reinterpret_cast< typename EnumToType<v>::type *>(u.constData() + byteOffset);
  260. + }
  261. +
  262. +} // namespace BufferTypeInfo
  263. +
  264. +} // namespace Qt3DCore
  265. +
  266. +QT_END_NAMESPACE
  267. +
  268. +
  269. +#endif // QT3DCORE_BUFFERUTILS_P_H
  270. diff --git a/src/core/geometry/buffervisitor_p.h b/src/core/geometry/buffervisitor_p.h
  271. new file mode 100644 (file)
  272. index 0000000..69cfb9b
  273. --- /dev/null
  274. +++ b/src/core/geometry/buffervisitor_p.h
  275. @@ -0,0 +1,285 @@
  276. +/****************************************************************************
  277. +**
  278. +** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
  279. +** Contact: https://www.qt.io/licensing/
  280. +**
  281. +** This file is part of the Qt3D module of the Qt Toolkit.
  282. +**
  283. +** $QT_BEGIN_LICENSE:LGPL$
  284. +** Commercial License Usage
  285. +** Licensees holding valid commercial Qt licenses may use this file in
  286. +** accordance with the commercial license agreement provided with the
  287. +** Software or, alternatively, in accordance with the terms contained in
  288. +** a written agreement between you and The Qt Company. For licensing terms
  289. +** and conditions see https://www.qt.io/terms-conditions. For further
  290. +** information use the contact form at https://www.qt.io/contact-us.
  291. +**
  292. +** GNU Lesser General Public License Usage
  293. +** Alternatively, this file may be used under the terms of the GNU Lesser
  294. +** General Public License version 3 as published by the Free Software
  295. +** Foundation and appearing in the file LICENSE.LGPL3 included in the
  296. +** packaging of this file. Please review the following information to
  297. +** ensure the GNU Lesser General Public License version 3 requirements
  298. +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
  299. +**
  300. +** GNU General Public License Usage
  301. +** Alternatively, this file may be used under the terms of the GNU
  302. +** General Public License version 2.0 or (at your option) the GNU General
  303. +** Public license version 3 or any later version approved by the KDE Free
  304. +** Qt Foundation. The licenses are as published by the Free Software
  305. +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
  306. +** included in the packaging of this file. Please review the following
  307. +** information to ensure the GNU General Public License requirements will
  308. +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
  309. +** https://www.gnu.org/licenses/gpl-3.0.html.
  310. +**
  311. +** $QT_END_LICENSE$
  312. +**
  313. +****************************************************************************/
  314. +
  315. +#ifndef QT3DCORE_BUFFERVISITOR_P_H
  316. +#define QT3DCORE_BUFFERVISITOR_P_H
  317. +
  318. +//
  319. +// W A R N I N G
  320. +// -------------
  321. +//
  322. +// This file is not part of the Qt API. It exists for the convenience
  323. +// of other Qt classes. This header file may change from version to
  324. +// version without notice, or even be removed.
  325. +//
  326. +// We mean it.
  327. +//
  328. +
  329. +#include <Qt3DCore/qnodeid.h>
  330. +#include <Qt3DCore/qattribute.h>
  331. +#include <Qt3DCore/qbuffer.h>
  332. +#include <Qt3DCore/private/bufferutils_p.h>
  333. +
  334. +QT_BEGIN_NAMESPACE
  335. +
  336. +namespace Qt3DCore {
  337. +class QEntity;
  338. +
  339. +template <typename ValueType, Qt3DCore::QAttribute::VertexBaseType VertexBaseType, uint dataSize>
  340. +class Q_AUTOTEST_EXPORT BufferVisitor
  341. +{
  342. +public:
  343. + explicit BufferVisitor() = default;
  344. + virtual ~BufferVisitor() = default;
  345. +
  346. + virtual void visit(uint ndx, ValueType x) {
  347. + Q_UNUSED(ndx) Q_UNUSED(x)
  348. + }
  349. + virtual void visit(uint ndx, ValueType x, ValueType y) {
  350. + Q_UNUSED(ndx) Q_UNUSED(x) Q_UNUSED(y)
  351. + }
  352. + virtual void visit(uint ndx, ValueType x, ValueType y, ValueType z) {
  353. + Q_UNUSED(ndx) Q_UNUSED(x) Q_UNUSED(y) Q_UNUSED(z)
  354. + }
  355. + virtual void visit(uint ndx, ValueType x, ValueType y, ValueType z, ValueType w) {
  356. + Q_UNUSED(ndx) Q_UNUSED(x) Q_UNUSED(y) Q_UNUSED(z) Q_UNUSED(w)
  357. + }
  358. +
  359. + bool apply(QAttribute *attribute,
  360. + QAttribute *indexAttribute,
  361. + int drawVertexCount,
  362. + bool primitiveRestartEnabled,
  363. + int primitiveRestartIndex)
  364. + {
  365. + if (attribute->vertexBaseType() != VertexBaseType)
  366. + return false;
  367. + if (attribute->vertexSize() < dataSize)
  368. + return false;
  369. +
  370. + auto data = attribute->buffer()->data();
  371. + auto vertexBuffer = BufferTypeInfo::castToType<VertexBaseType>(data, attribute->byteOffset());
  372. +
  373. + if (indexAttribute) {
  374. + auto indexData = indexAttribute->buffer()->data();
  375. + switch (indexAttribute->vertexBaseType()) {
  376. + case Qt3DCore::QAttribute::UnsignedShort: {
  377. + auto indexBuffer = BufferTypeInfo::castToType<Qt3DCore::QAttribute::UnsignedShort>(indexData, indexAttribute->byteOffset());
  378. + traverseCoordinateIndexed(vertexBuffer, indexBuffer, attribute->byteStride(), drawVertexCount,
  379. + primitiveRestartEnabled, primitiveRestartIndex);
  380. + break;
  381. + }
  382. + case Qt3DCore::QAttribute::UnsignedInt: {
  383. + auto indexBuffer = BufferTypeInfo::castToType<Qt3DCore::QAttribute::UnsignedInt>(indexData, indexAttribute->byteOffset());
  384. + traverseCoordinateIndexed(vertexBuffer, indexBuffer, attribute->byteStride(), drawVertexCount,
  385. + primitiveRestartEnabled, primitiveRestartIndex);
  386. + break;
  387. + }
  388. + case Qt3DCore::QAttribute::UnsignedByte: {
  389. + auto indexBuffer = BufferTypeInfo::castToType<Qt3DCore::QAttribute::UnsignedByte>(indexData, indexAttribute->byteOffset());
  390. + traverseCoordinateIndexed(vertexBuffer, indexBuffer, attribute->byteStride(), drawVertexCount,
  391. + primitiveRestartEnabled, primitiveRestartIndex);
  392. + break;
  393. + }
  394. + default: Q_UNREACHABLE();
  395. + }
  396. + } else {
  397. + switch (dataSize) {
  398. + case 1: traverseCoordinates1(vertexBuffer, attribute->byteStride(), drawVertexCount); break;
  399. + case 2: traverseCoordinates2(vertexBuffer, attribute->byteStride(), drawVertexCount); break;
  400. + case 3: traverseCoordinates3(vertexBuffer, attribute->byteStride(), drawVertexCount); break;
  401. + case 4: traverseCoordinates4(vertexBuffer, attribute->byteStride(), drawVertexCount); break;
  402. + default: Q_UNREACHABLE();
  403. + }
  404. + }
  405. +
  406. + return true;
  407. + }
  408. +
  409. +protected:
  410. + template<typename VertexBufferType, typename IndexBufferType>
  411. + void traverseCoordinateIndexed(VertexBufferType *vertexBuffer,
  412. + IndexBufferType *indexBuffer,
  413. + int vertexByteStride,
  414. + int drawVertexCount,
  415. + bool primitiveRestartEnabled,
  416. + int primitiveRestartIndex)
  417. + {
  418. + switch (dataSize) {
  419. + case 1: traverseCoordinates1Indexed(vertexBuffer, vertexByteStride, indexBuffer, drawVertexCount,
  420. + primitiveRestartEnabled, primitiveRestartIndex);
  421. + break;
  422. + case 2: traverseCoordinates2Indexed(vertexBuffer, vertexByteStride, indexBuffer, drawVertexCount,
  423. + primitiveRestartEnabled, primitiveRestartIndex);
  424. + break;
  425. + case 3: traverseCoordinates3Indexed(vertexBuffer, vertexByteStride, indexBuffer, drawVertexCount,
  426. + primitiveRestartEnabled, primitiveRestartIndex);
  427. + break;
  428. + case 4: traverseCoordinates4Indexed(vertexBuffer, vertexByteStride, indexBuffer, drawVertexCount,
  429. + primitiveRestartEnabled, primitiveRestartIndex);
  430. + break;
  431. + default: Q_UNREACHABLE();
  432. + }
  433. + }
  434. +
  435. + template <typename Coordinate>
  436. + void traverseCoordinates1(Coordinate *coordinates,
  437. + const uint byteStride,
  438. + const uint count)
  439. + {
  440. + const uint stride = byteStride / sizeof(Coordinate);
  441. + for (uint ndx = 0; ndx < count; ++ndx) {
  442. + visit(ndx, coordinates[0]);
  443. + coordinates += stride;
  444. + }
  445. + }
  446. +
  447. + template <typename Coordinate, typename IndexElem>
  448. + void traverseCoordinates1Indexed(Coordinate *coordinates,
  449. + const uint byteStride,
  450. + IndexElem *indices,
  451. + const uint count,
  452. + bool primitiveRestartEnabled,
  453. + int primitiveRestartIndex)
  454. + {
  455. + const uint stride = byteStride / sizeof(Coordinate);
  456. + for (uint i = 0; i < count; ++i) {
  457. + if (!primitiveRestartEnabled || static_cast<int>(indices[i]) != primitiveRestartIndex) {
  458. + const uint n = stride * indices[i];
  459. + visit(i, coordinates[n]);
  460. + }
  461. + }
  462. + }
  463. +
  464. + template <typename Coordinate>
  465. + void traverseCoordinates2(Coordinate *coordinates,
  466. + const uint byteStride,
  467. + const uint count)
  468. + {
  469. + const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 2;
  470. + for (uint ndx = 0; ndx < count; ++ndx) {
  471. + visit(ndx, coordinates[0], coordinates[1]);
  472. + coordinates += stride;
  473. + }
  474. + }
  475. +
  476. +
  477. + template <typename Coordinate, typename IndexElem>
  478. + void traverseCoordinates2Indexed(Coordinate *coordinates,
  479. + const uint byteStride,
  480. + IndexElem *indices,
  481. + const uint count,
  482. + bool primitiveRestartEnabled,
  483. + int primitiveRestartIndex)
  484. + {
  485. + const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 2;
  486. + for (uint i = 0; i < count; ++i) {
  487. + if (!primitiveRestartEnabled || static_cast<int>(indices[i]) != primitiveRestartIndex) {
  488. + const uint n = stride * indices[i];
  489. + visit(i, coordinates[n], coordinates[n + 1]);
  490. + }
  491. + }
  492. + }
  493. +
  494. + template <typename Coordinate>
  495. + void traverseCoordinates3(Coordinate *coordinates,
  496. + const uint byteStride,
  497. + const uint count)
  498. + {
  499. + const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 3;
  500. + for (uint ndx = 0; ndx < count; ++ndx) {
  501. + visit(ndx, coordinates[0], coordinates[1], coordinates[2]);
  502. + coordinates += stride;
  503. + }
  504. + }
  505. +
  506. + template <typename Coordinate, typename IndexElem>
  507. + void traverseCoordinates3Indexed(Coordinate *coordinates,
  508. + const uint byteStride,
  509. + IndexElem *indices,
  510. + const uint count,
  511. + bool primitiveRestartEnabled,
  512. + int primitiveRestartIndex)
  513. + {
  514. + const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 3;
  515. + for (uint i = 0; i < count; ++i) {
  516. + if (!primitiveRestartEnabled || static_cast<int>(indices[i]) != primitiveRestartIndex) {
  517. + const uint n = stride * indices[i];
  518. + visit(i, coordinates[n], coordinates[n + 1], coordinates[n + 2]);
  519. + }
  520. + }
  521. + }
  522. +
  523. + template <typename Coordinate>
  524. + void traverseCoordinates4(Coordinate *coordinates,
  525. + const uint byteStride,
  526. + const uint count)
  527. + {
  528. + const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 4;
  529. + for (uint ndx = 0; ndx < count; ++ndx) {
  530. + visit(ndx, coordinates[0], coordinates[1], coordinates[2], coordinates[3]);
  531. + coordinates += stride;
  532. + }
  533. + }
  534. +
  535. + template <typename Coordinate, typename IndexElem>
  536. + void traverseCoordinates4Indexed(Coordinate *coordinates,
  537. + const uint byteStride,
  538. + IndexElem *indices,
  539. + const uint count,
  540. + bool primitiveRestartEnabled,
  541. + int primitiveRestartIndex)
  542. + {
  543. + const uint stride = byteStride ? byteStride / sizeof(Coordinate) : 4;
  544. + for (uint i = 0; i < count; ++i) {
  545. + if (!primitiveRestartEnabled || static_cast<int>(indices[i]) != primitiveRestartIndex) {
  546. + const uint n = stride * indices[i];
  547. + visit(i, coordinates[n], coordinates[n + 1], coordinates[n + 2], coordinates[n + 3]);
  548. + }
  549. + }
  550. + }
  551. +};
  552. +
  553. +typedef BufferVisitor<float, Qt3DCore::QAttribute::Float, 3> Buffer3fVisitor;
  554. +
  555. +} // namespace Qt3DCore
  556. +
  557. +QT_END_NAMESPACE
  558. +
  559. +
  560. +#endif // QT3DCORE_BUFFERVISITOR_P_H
  561. diff --git a/src/core/geometry/geometry.pri b/src/core/geometry/geometry.pri
  562. index eadf7ca..70bda07 100644 (file)
  563. --- a/src/core/geometry/geometry.pri
  564. +++ b/src/core/geometry/geometry.pri
  565. @@ -12,7 +12,9 @@ HEADERS += \
  566. $$PWD/qgeometry.h \
  567. $$PWD/qgeometryfactory_p.h \
  568. $$PWD/qgeometryview_p.h \
  569. - $$PWD/qgeometryview.h
  570. + $$PWD/qgeometryview.h \
  571. + $$PWD/bufferutils_p.h \
  572. + $$PWD/buffervisitor_p.h
  573. SOURCES += \
  574. $$PWD/qabstractfunctor.cpp \
  575. diff --git a/src/core/geometry/qgeometry_p.h b/src/core/geometry/qgeometry_p.h
  576. index 2a05b5b..ed13b3f 100644 (file)
  577. --- a/src/core/geometry/qgeometry_p.h
  578. +++ b/src/core/geometry/qgeometry_p.h
  579. @@ -72,7 +72,6 @@ public:
  580. void setScene(QScene *scene) override;
  581. void update() override;
  582. void setExtent(const QVector3D &minExtent, const QVector3D &maxExtent);
  583. -
  584. static QGeometryPrivate *get(QGeometry *q);
  585. QVector<QAttribute *> m_attributes;
  586. diff --git a/src/core/geometry/qgeometryview.cpp b/src/core/geometry/qgeometryview.cpp
  587. index 65e30d9..258448b 100644 (file)
  588. --- a/src/core/geometry/qgeometryview.cpp
  589. +++ b/src/core/geometry/qgeometryview.cpp
  590. @@ -39,11 +39,250 @@
  591. #include "qgeometryview.h"
  592. #include "qgeometryview_p.h"
  593. +#include "qgeometry_p.h"
  594. +#include "buffervisitor_p.h"
  595. +
  596. +#include <Qt3DCore/QAttribute>
  597. +#include <Qt3DCore/QBuffer>
  598. +#include <Qt3DCore/private/vector3d_p.h>
  599. QT_BEGIN_NAMESPACE
  600. using namespace Qt3DCore;
  601. +namespace {
  602. +
  603. +class FindExtremePoints : public Buffer3fVisitor
  604. +{
  605. +public:
  606. + FindExtremePoints()
  607. + : Buffer3fVisitor()
  608. + , xMin(0.0f), xMax(0.0f), yMin(0.0f), yMax(0.0f), zMin(0.0f), zMax(0.0f)
  609. + { }
  610. +
  611. + float xMin, xMax, yMin, yMax, zMin, zMax;
  612. + Vector3D xMinPt, xMaxPt, yMinPt, yMaxPt, zMinPt, zMaxPt;
  613. +
  614. + void visit(uint ndx, float x, float y, float z) override
  615. + {
  616. + if (ndx) {
  617. + if (x < xMin) {
  618. + xMin = x;
  619. + xMinPt = Vector3D(x, y, z);
  620. + }
  621. + if (x > xMax) {
  622. + xMax = x;
  623. + xMaxPt = Vector3D(x, y, z);
  624. + }
  625. + if (y < yMin) {
  626. + yMin = y;
  627. + yMinPt = Vector3D(x, y, z);
  628. + }
  629. + if (y > yMax) {
  630. + yMax = y;
  631. + yMaxPt = Vector3D(x, y, z);
  632. + }
  633. + if (z < zMin) {
  634. + zMin = z;
  635. + zMinPt = Vector3D(x, y, z);
  636. + }
  637. + if (z > zMax) {
  638. + zMax = z;
  639. + zMaxPt = Vector3D(x, y, z);
  640. + }
  641. + } else {
  642. + xMin = xMax = x;
  643. + yMin = yMax = y;
  644. + zMin = zMax = z;
  645. + xMinPt = xMaxPt = yMinPt = yMaxPt = zMinPt = zMaxPt = Vector3D(x, y, z);
  646. + }
  647. + }
  648. +};
  649. +
  650. +class FindMaxDistantPoint : public Buffer3fVisitor
  651. +{
  652. +public:
  653. + FindMaxDistantPoint()
  654. + : Buffer3fVisitor()
  655. + { }
  656. +
  657. + float maxLengthSquared = 0.0f;
  658. + bool setReferencePoint = false;
  659. + bool hasNoPoints = true;
  660. + Vector3D maxDistPt;
  661. + Vector3D referencePt;
  662. +
  663. + void visit(uint ndx, float x, float y, float z) override
  664. + {
  665. + Q_UNUSED(ndx)
  666. + const Vector3D p = Vector3D(x, y, z);
  667. +
  668. + if (hasNoPoints && setReferencePoint) {
  669. + maxLengthSquared = 0.0f;
  670. + referencePt = p;
  671. + }
  672. + const float lengthSquared = (p - referencePt).lengthSquared();
  673. + if ( lengthSquared >= maxLengthSquared ) {
  674. + maxDistPt = p;
  675. + maxLengthSquared = lengthSquared;
  676. + }
  677. + hasNoPoints = false;
  678. + }
  679. +};
  680. +
  681. +std::pair<QVector3D, QVector3D> calculateLocalBoundingVolume(QGeometryView *node)
  682. +{
  683. + // The Bounding volume will only be computed if the position Buffer
  684. + // isDirty
  685. +
  686. + if (!node->isEnabled())
  687. + return {};
  688. +
  689. + if (node->primitiveType() == QGeometryView::Patches)
  690. + return {};
  691. +
  692. + QGeometry *geom = node->geometry();
  693. + QGeometryPrivate *dgeom = QGeometryPrivate::get(geom);
  694. +
  695. + if (!geom)
  696. + return {};
  697. +
  698. + int drawVertexCount = node->vertexCount(); // may be 0, gets changed below if so
  699. +
  700. + QAttribute *positionAttribute = dgeom->m_boundingVolumePositionAttribute;
  701. + const QVector<Qt3DCore::QAttribute *> attributes = geom->attributes();
  702. +
  703. + // Use the default position attribute if attribute is null
  704. + if (!positionAttribute) {
  705. + for (QAttribute *attr : attributes) {
  706. + if (attr->name() == QAttribute::defaultPositionAttributeName()) {
  707. + positionAttribute = attr;
  708. + break;
  709. + }
  710. + }
  711. + }
  712. +
  713. + if (!positionAttribute
  714. + || positionAttribute->attributeType() != QAttribute::VertexAttribute
  715. + || positionAttribute->vertexBaseType() != QAttribute::Float
  716. + || positionAttribute->vertexSize() < 3) {
  717. + qWarning("calculateLocalBoundingVolume: Position attribute not suited for bounding volume computation");
  718. + return {};
  719. + }
  720. +
  721. + Qt3DCore::QBuffer *buf = positionAttribute->buffer();
  722. + // No point in continuing if the positionAttribute doesn't have a suitable buffer
  723. + if (!buf) {
  724. + qWarning("calculateLocalBoundingVolume: Position attribute not referencing a valid buffer");
  725. + return {};
  726. + }
  727. +
  728. + // Check if there is an index attribute.
  729. + QAttribute *indexAttribute = nullptr;
  730. + Qt3DCore::QBuffer *indexBuf = nullptr;
  731. +
  732. + for (const auto attr : attributes) {
  733. + if (attr->attributeType() == QAttribute::IndexAttribute) {
  734. + indexBuf = attr->buffer();
  735. + if (indexBuf) {
  736. + indexAttribute = attr;
  737. +
  738. + if (!drawVertexCount)
  739. + drawVertexCount = static_cast<int>(indexAttribute->count());
  740. +
  741. + static const QAttribute::VertexBaseType validIndexTypes[] = {
  742. + QAttribute::UnsignedShort,
  743. + QAttribute::UnsignedInt,
  744. + QAttribute::UnsignedByte
  745. + };
  746. +
  747. + if (std::find(std::begin(validIndexTypes),
  748. + std::end(validIndexTypes),
  749. + indexAttribute->vertexBaseType()) == std::end(validIndexTypes)) {
  750. + qWarning() << "calculateLocalBoundingVolume: Unsupported index attribute type" << indexAttribute->name() << indexAttribute->vertexBaseType();
  751. + return {};
  752. + }
  753. +
  754. + break;
  755. + }
  756. + }
  757. + }
  758. +
  759. + if (!indexAttribute && !drawVertexCount)
  760. + drawVertexCount = static_cast<int>(positionAttribute->count());
  761. +
  762. + // Buf will be set to not dirty once it's loaded
  763. + // in a job executed after this one
  764. + // We need to recompute the bounding volume
  765. + // If anything in the GeometryRenderer has changed
  766. + BoundingVolumeCalculator reader;
  767. + if (reader.apply(positionAttribute, indexAttribute, drawVertexCount,
  768. + node->primitiveRestartEnabled(), node->restartIndexValue()))
  769. + return {reader.min(), reader.max()};
  770. +
  771. + return {};
  772. +}
  773. +
  774. +}
  775. +
  776. +
  777. +bool BoundingVolumeCalculator::apply(QAttribute *positionAttribute,
  778. + QAttribute *indexAttribute,
  779. + int drawVertexCount,
  780. + bool primitiveRestartEnabled,
  781. + int primitiveRestartIndex)
  782. +{
  783. + m_radius = -1.f;
  784. +
  785. + FindExtremePoints findExtremePoints;
  786. + if (!findExtremePoints.apply(positionAttribute, indexAttribute, drawVertexCount,
  787. + primitiveRestartEnabled, primitiveRestartIndex)) {
  788. + return false;
  789. + }
  790. +
  791. + m_min = QVector3D(findExtremePoints.xMin, findExtremePoints.yMin, findExtremePoints.zMin);
  792. + m_max = QVector3D(findExtremePoints.xMax, findExtremePoints.yMax, findExtremePoints.zMax);
  793. +
  794. + FindMaxDistantPoint maxDistantPointY;
  795. + maxDistantPointY.setReferencePoint = true;
  796. + if (!maxDistantPointY.apply(positionAttribute, indexAttribute, drawVertexCount,
  797. + primitiveRestartEnabled, primitiveRestartIndex)) {
  798. + return false;
  799. + }
  800. + if (maxDistantPointY.hasNoPoints)
  801. + return false;
  802. +
  803. + //const Vector3D x = maxDistantPointY.referencePt;
  804. + const Vector3D y = maxDistantPointY.maxDistPt;
  805. +
  806. + FindMaxDistantPoint maxDistantPointZ;
  807. + maxDistantPointZ.setReferencePoint = false;
  808. + maxDistantPointZ.referencePt = y;
  809. + if (!maxDistantPointZ.apply(positionAttribute, indexAttribute, drawVertexCount,
  810. + primitiveRestartEnabled, primitiveRestartIndex))
  811. + return false;
  812. + const Vector3D z = maxDistantPointZ.maxDistPt;
  813. + const Vector3D center = (y + z) * .5f;
  814. +
  815. + FindMaxDistantPoint maxDistantPointCenter;
  816. + maxDistantPointCenter.setReferencePoint = false;
  817. + maxDistantPointCenter.referencePt = center;
  818. + if (!maxDistantPointCenter.apply(positionAttribute, indexAttribute, drawVertexCount,
  819. + primitiveRestartEnabled, primitiveRestartIndex))
  820. + return false;
  821. +
  822. + const float radius = (center - maxDistantPointCenter.maxDistPt).length();
  823. +
  824. + if (center == Vector3D{} || radius < 0.f)
  825. + return false;
  826. +
  827. + m_radius = radius;
  828. + m_center = QVector3D{ center.x(), center.y(), center.z() };
  829. +
  830. + return true;
  831. +}
  832. +
  833. +
  834. QGeometryViewPrivate::QGeometryViewPrivate()
  835. : QNodePrivate()
  836. , m_instanceCount(1)
  837. @@ -65,6 +304,11 @@ QGeometryViewPrivate::~QGeometryViewPrivate()
  838. {
  839. }
  840. +QGeometryViewPrivate *QGeometryViewPrivate::get(QGeometryView *q)
  841. +{
  842. + return q->d_func();
  843. +}
  844. +
  845. void QGeometryViewPrivate::update()
  846. {
  847. if (!m_blockNotifications)
  848. diff --git a/src/core/geometry/qgeometryview_p.h b/src/core/geometry/qgeometryview_p.h
  849. index f806c4d..05dea1d 100644 (file)
  850. --- a/src/core/geometry/qgeometryview_p.h
  851. +++ b/src/core/geometry/qgeometryview_p.h
  852. @@ -55,6 +55,8 @@
  853. #include <Qt3DCore/qgeometryview.h>
  854. #include <Qt3DCore/private/qgeometryfactory_p.h>
  855. #include <Qt3DCore/private/qt3dcore_global_p.h>
  856. +
  857. +#include <QtGui/qvector3d.h>
  858. #include <memory>
  859. QT_BEGIN_NAMESPACE
  860. @@ -67,6 +69,8 @@ public:
  861. QGeometryViewPrivate();
  862. ~QGeometryViewPrivate();
  863. + static QGeometryViewPrivate *get(QGeometryView *q);
  864. +
  865. void update() override;
  866. Q_DECLARE_PUBLIC(QGeometryView)
  867. @@ -85,6 +89,30 @@ public:
  868. bool m_dirty;
  869. };
  870. +class BoundingVolumeCalculator
  871. +{
  872. +public:
  873. + BoundingVolumeCalculator() = default;
  874. +
  875. + const QVector3D min() const { return m_min; }
  876. + const QVector3D max() const { return m_max; }
  877. + const QVector3D center() const { return m_center; }
  878. + float radius() const { return m_radius; }
  879. + bool isValid() const { return m_radius >= 0.f; }
  880. +
  881. + bool apply(QAttribute *positionAttribute,
  882. + QAttribute *indexAttribute,
  883. + int drawVertexCount,
  884. + bool primitiveRestartEnabled,
  885. + int primitiveRestartIndex);
  886. +
  887. +private:
  888. + QVector3D m_min;
  889. + QVector3D m_max;
  890. + QVector3D m_center;
  891. + float m_radius = -1.f;
  892. +};
  893. +
  894. } // namespace Qt3DCore
  895. QT_END_NAMESPACE
  896. diff --git a/src/core/jobs/calcboundingvolumejob.cpp b/src/core/jobs/calcboundingvolumejob.cpp
  897. new file mode 100644 (file)
  898. index 0000000..37ee92e
  899. --- /dev/null
  900. +++ b/src/core/jobs/calcboundingvolumejob.cpp
  901. @@ -0,0 +1,317 @@
  902. +/****************************************************************************
  903. +**
  904. +** Copyright (C) 2020 Klaralvdalens Datakonsult AB (KDAB).
  905. +** Contact: https://www.qt.io/licensing/
  906. +**
  907. +** This file is part of the Qt3D module of the Qt Toolkit.
  908. +**
  909. +** $QT_BEGIN_LICENSE:LGPL$
  910. +** Commercial License Usage
  911. +** Licensees holding valid commercial Qt licenses may use this file in
  912. +** accordance with the commercial license agreement provided with the
  913. +** Software or, alternatively, in accordance with the terms contained in
  914. +** a written agreement between you and The Qt Company. For licensing terms
  915. +** and conditions see https://www.qt.io/terms-conditions. For further
  916. +** information use the contact form at https://www.qt.io/contact-us.
  917. +**
  918. +** GNU Lesser General Public License Usage
  919. +** Alternatively, this file may be used under the terms of the GNU Lesser
  920. +** General Public License version 3 as published by the Free Software
  921. +** Foundation and appearing in the file LICENSE.LGPL3 included in the
  922. +** packaging of this file. Please review the following information to
  923. +** ensure the GNU Lesser General Public License version 3 requirements
  924. +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
  925. +**
  926. +** GNU General Public License Usage
  927. +** Alternatively, this file may be used under the terms of the GNU
  928. +** General Public License version 2.0 or (at your option) the GNU General
  929. +** Public license version 3 or any later version approved by the KDE Free
  930. +** Qt Foundation. The licenses are as published by the Free Software
  931. +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
  932. +** included in the packaging of this file. Please review the following
  933. +** information to ensure the GNU General Public License requirements will
  934. +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
  935. +** https://www.gnu.org/licenses/gpl-3.0.html.
  936. +**
  937. +** $QT_END_LICENSE$
  938. +**
  939. +****************************************************************************/
  940. +
  941. +#include "calcboundingvolumejob_p.h"
  942. +
  943. +#include <Qt3DCore/qattribute.h>
  944. +#include <Qt3DCore/qboundingvolume.h>
  945. +#include <Qt3DCore/qbuffer.h>
  946. +#include <Qt3DCore/qgeometryview.h>
  947. +#include <Qt3DCore/private/job_common_p.h>
  948. +#include <Qt3DCore/private/qaspectjob_p.h>
  949. +#include <Qt3DCore/private/qaspectmanager_p.h>
  950. +#include <Qt3DCore/private/qattribute_p.h>
  951. +#include <Qt3DCore/private/qboundingvolume_p.h>
  952. +#include <Qt3DCore/private/qbuffer_p.h>
  953. +#include <Qt3DCore/private/qentity_p.h>
  954. +#include <Qt3DCore/private/qgeometry_p.h>
  955. +#include <Qt3DCore/private/qgeometryview_p.h>
  956. +#include <Qt3DCore/private/qnodevisitor_p.h>
  957. +
  958. +#include <QtCore/qmath.h>
  959. +#if QT_CONFIG(concurrent)
  960. +#include <QtConcurrent/QtConcurrent>
  961. +#endif
  962. +
  963. +QT_BEGIN_NAMESPACE
  964. +
  965. +namespace Qt3DCore {
  966. +
  967. +namespace {
  968. +
  969. +BoundingVolumeComputeData findBoundingVolumeComputeData(QGeometryView *node)
  970. +{
  971. + if (!node->isEnabled())
  972. + return {};
  973. +
  974. + if (node->primitiveType() == QGeometryView::Patches)
  975. + return {};
  976. +
  977. + QGeometry *geom = node->geometry();
  978. + QGeometryPrivate *dgeom = QGeometryPrivate::get(geom);
  979. + if (!geom)
  980. + return {};
  981. +
  982. + int drawVertexCount = node->vertexCount(); // may be 0, gets changed below if so
  983. +
  984. + QAttribute *positionAttribute = dgeom->m_boundingVolumePositionAttribute;
  985. + const QVector<Qt3DCore::QAttribute *> attributes = geom->attributes();
  986. +
  987. + // Use the default position attribute if attribute is null
  988. + if (!positionAttribute) {
  989. + for (QAttribute *attr : attributes) {
  990. + if (attr->name() == QAttribute::defaultPositionAttributeName()) {
  991. + positionAttribute = attr;
  992. + break;
  993. + }
  994. + }
  995. + }
  996. +
  997. + if (!positionAttribute
  998. + || positionAttribute->attributeType() != QAttribute::VertexAttribute
  999. + || positionAttribute->vertexBaseType() != QAttribute::Float
  1000. + || positionAttribute->vertexSize() < 3) {
  1001. + qWarning("findBoundingVolumeComputeData: Position attribute not suited for bounding volume computation");
  1002. + return {};
  1003. + }
  1004. +
  1005. + Qt3DCore::QBuffer *positionBuffer = positionAttribute->buffer();
  1006. + // No point in continuing if the positionAttribute doesn't have a suitable buffer
  1007. + if (!positionBuffer) {
  1008. + qWarning("findBoundingVolumeComputeData: Position attribute not referencing a valid buffer");
  1009. + return {};
  1010. + }
  1011. +
  1012. + // Check if there is an index attribute.
  1013. + QAttribute *indexAttribute = nullptr;
  1014. + Qt3DCore::QBuffer *indexBuffer = nullptr;
  1015. +
  1016. + for (const auto attr : attributes) {
  1017. + if (attr->attributeType() == QAttribute::IndexAttribute) {
  1018. + indexBuffer = attr->buffer();
  1019. + if (indexBuffer) {
  1020. + indexAttribute = attr;
  1021. +
  1022. + if (!drawVertexCount)
  1023. + drawVertexCount = static_cast<int>(indexAttribute->count());
  1024. +
  1025. + static const QAttribute::VertexBaseType validIndexTypes[] = {
  1026. + QAttribute::UnsignedShort,
  1027. + QAttribute::UnsignedInt,
  1028. + QAttribute::UnsignedByte
  1029. + };
  1030. +
  1031. + if (std::find(std::begin(validIndexTypes),
  1032. + std::end(validIndexTypes),
  1033. + indexAttribute->vertexBaseType()) == std::end(validIndexTypes)) {
  1034. + qWarning() << "findBoundingVolumeComputeData: Unsupported index attribute type" << indexAttribute->name() << indexAttribute->vertexBaseType();
  1035. + return {};
  1036. + }
  1037. +
  1038. + break;
  1039. + }
  1040. + }
  1041. + }
  1042. +
  1043. + if (!indexAttribute && !drawVertexCount)
  1044. + drawVertexCount = static_cast<int>(positionAttribute->count());
  1045. +
  1046. + return { nullptr, nullptr, positionAttribute, indexAttribute, drawVertexCount };
  1047. +}
  1048. +
  1049. +BoundingVolumeComputeResult calculateLocalBoundingVolume(const BoundingVolumeComputeData &data) {
  1050. + BoundingVolumeCalculator calculator;
  1051. + if (calculator.apply(data.positionAttribute, data.indexAttribute, data.vertexCount,
  1052. + data.provider->view()->primitiveRestartEnabled(),
  1053. + data.provider->view()->restartIndexValue()))
  1054. + return {
  1055. + data.entity, data.provider, data.positionAttribute, data.indexAttribute,
  1056. + calculator.min(), calculator.max(),
  1057. + calculator.center(), calculator.radius()
  1058. + };
  1059. + return {};
  1060. +}
  1061. +
  1062. +bool isTreeEnabled(QEntity *entity) {
  1063. + if (!entity->isEnabled())
  1064. + return false;
  1065. +
  1066. + QEntity *parent = entity->parentEntity();
  1067. + while (parent) {
  1068. + if (!parent->isEnabled())
  1069. + return false;
  1070. + parent = parent->parentEntity();
  1071. + }
  1072. +
  1073. + return true;
  1074. +}
  1075. +
  1076. +struct UpdateBoundFunctor
  1077. +{
  1078. + // This define is required to work with QtConcurrent
  1079. + typedef QVector<BoundingVolumeComputeResult> result_type;
  1080. + result_type operator ()(const BoundingVolumeComputeData &data)
  1081. + {
  1082. + return { calculateLocalBoundingVolume(data) };
  1083. + }
  1084. +};
  1085. +
  1086. +struct ReduceUpdateBoundFunctor
  1087. +{
  1088. + void operator ()(QVector<BoundingVolumeComputeResult> &result, const QVector<BoundingVolumeComputeResult> &values)
  1089. + {
  1090. + result += values;
  1091. + }
  1092. +};
  1093. +
  1094. +} // anonymous
  1095. +
  1096. +//class CalculateBoundingVolumeJobPrivate : public Qt3DCore::QAspectJobPrivate
  1097. +//{
  1098. +//public:
  1099. +// CalculateBoundingVolumeJobPrivate() { }
  1100. +// ~CalculateBoundingVolumeJobPrivate() override { }
  1101. +
  1102. +// void postFrame(Qt3DCore::QAspectManager *manager) override
  1103. +// {
  1104. +// Q_UNUSED(manager)
  1105. +//// for (Geometry *backend : qAsConst(m_updatedGeometries)) {
  1106. +//// Qt3DCore::QGeometry *node = qobject_cast<Qt3DCore::QGeometry *>(manager->lookupNode(backend->peerId()));
  1107. +//// if (!node)
  1108. +//// continue;
  1109. +//// Qt3DCore::QGeometryPrivate *dNode = static_cast<Qt3DCore::QGeometryPrivate *>(Qt3DCore::QNodePrivate::get(node));
  1110. +//// dNode->setExtent(backend->min(), backend->max());
  1111. +//// }
  1112. +// }
  1113. +
  1114. +//};
  1115. +
  1116. +CalculateBoundingVolumeJob::CalculateBoundingVolumeJob()
  1117. + : Qt3DCore::QAspectJob()
  1118. + , m_root(nullptr)
  1119. +{
  1120. + SET_JOB_RUN_STAT_TYPE(this, JobTypes::CalcBoundingVolume, 0)
  1121. +}
  1122. +
  1123. +void CalculateBoundingVolumeJob::run()
  1124. +{
  1125. + m_results.clear();
  1126. +
  1127. + QHash<QEntity *, BoundingVolumeComputeData> dirtyEntities;
  1128. + QNodeVisitor visitor;
  1129. + visitor.traverse(m_root, [](QNode *) {}, [&dirtyEntities](QEntity *entity) {
  1130. + if (!isTreeEnabled(entity))
  1131. + return;
  1132. +
  1133. + const auto bvProviders = entity->componentsOfType<QBoundingVolume>();
  1134. + if (bvProviders.isEmpty())
  1135. + return;
  1136. +
  1137. + // we go through the list until be find a dirty provider,
  1138. + // or THE primary provider
  1139. + bool foundBV = false;
  1140. + for (auto bv: bvProviders) {
  1141. + if (!bv->view())
  1142. + continue;
  1143. + auto dbv = QBoundingVolumePrivate::get(bv);
  1144. + if (foundBV && !dbv->m_primaryProvider)
  1145. + continue;
  1146. +
  1147. + auto bvdata = findBoundingVolumeComputeData(bv->view());
  1148. + if (!bvdata.valid())
  1149. + continue;
  1150. + bvdata.entity = entity;
  1151. + bvdata.provider = bv;
  1152. +
  1153. + bool dirty = QEntityPrivate::get(entity)->m_dirty;
  1154. + dirty |= QGeometryViewPrivate::get(bv->view())->m_dirty;
  1155. + dirty |= QGeometryPrivate::get(bv->view()->geometry())->m_dirty;
  1156. + dirty |= QAttributePrivate::get(bvdata.positionAttribute)->m_dirty;
  1157. + dirty |= QBufferPrivate::get(bvdata.positionAttribute->buffer())->m_dirty;
  1158. + if (bvdata.indexAttribute) {
  1159. + dirty |= QAttributePrivate::get(bvdata.indexAttribute)->m_dirty;
  1160. + dirty |= QBufferPrivate::get(bvdata.indexAttribute->buffer())->m_dirty;
  1161. + }
  1162. +
  1163. + if (dbv->m_primaryProvider) {
  1164. + if (dirty)
  1165. + dirtyEntities[entity] = bvdata;
  1166. + break;
  1167. + } else if (dirty) {
  1168. + dirtyEntities[entity] = bvdata;
  1169. + foundBV = true;
  1170. + }
  1171. + }
  1172. + });
  1173. +
  1174. +#if QT_CONFIG(concurrent)
  1175. + if (dirtyEntities.size() > 1) {
  1176. + UpdateBoundFunctor functor;
  1177. + ReduceUpdateBoundFunctor reduceFunctor;
  1178. + m_results = QtConcurrent::blockingMappedReduced<decltype(m_results)>(dirtyEntities, functor, reduceFunctor);
  1179. + } else
  1180. +#endif
  1181. + {
  1182. + for (auto it = dirtyEntities.begin(); it != dirtyEntities.end(); ++it) {
  1183. + auto res = calculateLocalBoundingVolume(it.value());
  1184. + if (res.valid())
  1185. + m_results.push_back(res); // How do we push it to the backends????
  1186. + }
  1187. + }
  1188. +
  1189. + for (auto result: qAsConst(m_results)) {
  1190. + // set the results
  1191. + QBoundingVolumePrivate::get(result.provider)->setImplicitBounds(result.m_min, result.m_max, result.m_center, result.m_radius);
  1192. + }
  1193. +}
  1194. +
  1195. +void CalculateBoundingVolumeJob::postFrame(QAspectEngine *aspectEngine)
  1196. +{
  1197. + Q_UNUSED(aspectEngine)
  1198. +
  1199. + for (auto result: qAsConst(m_results)) {
  1200. + // reset dirty flags
  1201. + QEntityPrivate::get(result.entity)->m_dirty = false;
  1202. + QGeometryViewPrivate::get(result.provider->view())->m_dirty = false;
  1203. + QGeometryPrivate::get(result.provider->view()->geometry())->m_dirty = false;
  1204. + QAttributePrivate::get(result.positionAttribute)->m_dirty = false;
  1205. + QBufferPrivate::get(result.positionAttribute->buffer())->m_dirty = false;
  1206. + if (result.indexAttribute) {
  1207. + QAttributePrivate::get(result.indexAttribute)->m_dirty = false;
  1208. + QBufferPrivate::get(result.indexAttribute->buffer())->m_dirty = false;
  1209. + }
  1210. + }
  1211. +
  1212. + m_results.clear();
  1213. +}
  1214. +
  1215. +} // namespace Qt3DCore
  1216. +
  1217. +QT_END_NAMESPACE
  1218. +
  1219. diff --git a/src/core/jobs/calcboundingvolumejob_p.h b/src/core/jobs/calcboundingvolumejob_p.h
  1220. new file mode 100644 (file)
  1221. index 0000000..498fe76
  1222. --- /dev/null
  1223. +++ b/src/core/jobs/calcboundingvolumejob_p.h
  1224. @@ -0,0 +1,113 @@
  1225. +/****************************************************************************
  1226. +**
  1227. +** Copyright (C) 2020 Klaralvdalens Datakonsult AB (KDAB).
  1228. +** Contact: https://www.qt.io/licensing/
  1229. +**
  1230. +** This file is part of the Qt3D module of the Qt Toolkit.
  1231. +**
  1232. +** $QT_BEGIN_LICENSE:LGPL$
  1233. +** Commercial License Usage
  1234. +** Licensees holding valid commercial Qt licenses may use this file in
  1235. +** accordance with the commercial license agreement provided with the
  1236. +** Software or, alternatively, in accordance with the terms contained in
  1237. +** a written agreement between you and The Qt Company. For licensing terms
  1238. +** and conditions see https://www.qt.io/terms-conditions. For further
  1239. +** information use the contact form at https://www.qt.io/contact-us.
  1240. +**
  1241. +** GNU Lesser General Public License Usage
  1242. +** Alternatively, this file may be used under the terms of the GNU Lesser
  1243. +** General Public License version 3 as published by the Free Software
  1244. +** Foundation and appearing in the file LICENSE.LGPL3 included in the
  1245. +** packaging of this file. Please review the following information to
  1246. +** ensure the GNU Lesser General Public License version 3 requirements
  1247. +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
  1248. +**
  1249. +** GNU General Public License Usage
  1250. +** Alternatively, this file may be used under the terms of the GNU
  1251. +** General Public License version 2.0 or (at your option) the GNU General
  1252. +** Public license version 3 or any later version approved by the KDE Free
  1253. +** Qt Foundation. The licenses are as published by the Free Software
  1254. +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
  1255. +** included in the packaging of this file. Please review the following
  1256. +** information to ensure the GNU General Public License requirements will
  1257. +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
  1258. +** https://www.gnu.org/licenses/gpl-3.0.html.
  1259. +**
  1260. +** $QT_END_LICENSE$
  1261. +**
  1262. +****************************************************************************/
  1263. +
  1264. +#ifndef QT3DCORE_CALCBOUNDINGVOLUMEJOB_H
  1265. +#define QT3DCORE_CALCBOUNDINGVOLUMEJOB_H
  1266. +
  1267. +//
  1268. +// W A R N I N G
  1269. +// -------------
  1270. +//
  1271. +// This file is not part of the Qt API. It exists purely as an
  1272. +// implementation detail. This header file may change from version to
  1273. +// version without notice, or even be removed.
  1274. +//
  1275. +// We mean it.
  1276. +//
  1277. +
  1278. +#include <Qt3DCore/qaspectjob.h>
  1279. +#include <Qt3DCore/private/qt3dcore_global_p.h>
  1280. +
  1281. +#include <QtCore/QSharedPointer>
  1282. +#include <QtGui/qvector3d.h>
  1283. +
  1284. +QT_BEGIN_NAMESPACE
  1285. +
  1286. +namespace Qt3DCore {
  1287. +
  1288. +class CalculateBoundingVolumeJobPrivate;
  1289. +class QEntity;
  1290. +class QAttribute;
  1291. +class QBoundingVolume;
  1292. +
  1293. +struct BoundingVolumeComputeData {
  1294. + QEntity *entity = nullptr;
  1295. + QBoundingVolume *provider = nullptr;
  1296. + QAttribute *positionAttribute = nullptr;
  1297. + QAttribute *indexAttribute = nullptr;
  1298. + int vertexCount = 0;
  1299. +
  1300. + bool valid() const { return positionAttribute != nullptr; }
  1301. +};
  1302. +
  1303. +struct BoundingVolumeComputeResult {
  1304. + QEntity *entity = nullptr;
  1305. + QBoundingVolume *provider = nullptr;
  1306. + QAttribute *positionAttribute = nullptr;
  1307. + QAttribute *indexAttribute = nullptr;
  1308. + QVector3D m_min;
  1309. + QVector3D m_max;
  1310. + QVector3D m_center;
  1311. + float m_radius = -1.f;
  1312. +
  1313. + bool valid() const { return m_radius >= 0.f; }
  1314. +};
  1315. +
  1316. +class Q_3DCORE_PRIVATE_EXPORT CalculateBoundingVolumeJob : public Qt3DCore::QAspectJob
  1317. +{
  1318. +public:
  1319. + explicit CalculateBoundingVolumeJob();
  1320. +
  1321. + void setRoot(QEntity *root) { m_root = root; }
  1322. + void run() override;
  1323. + void postFrame(QAspectEngine *aspectEngine) override;
  1324. +
  1325. +private:
  1326. + Q_DECLARE_PRIVATE(CalculateBoundingVolumeJob)
  1327. + QEntity *m_root;
  1328. + QVector<BoundingVolumeComputeResult> m_results;
  1329. +};
  1330. +
  1331. +typedef QSharedPointer<CalculateBoundingVolumeJob> CalculateBoundingVolumeJobPtr;
  1332. +
  1333. +} // namespace Qt3DCore
  1334. +
  1335. +QT_END_NAMESPACE
  1336. +
  1337. +#endif // QT3DCORE_CALCBOUNDINGVOLUMEJOB_H
  1338. diff --git a/src/core/jobs/job_common_p.h b/src/core/jobs/job_common_p.h
  1339. new file mode 100644 (file)
  1340. index 0000000..6cbf178
  1341. --- /dev/null
  1342. +++ b/src/core/jobs/job_common_p.h
  1343. @@ -0,0 +1,73 @@
  1344. +/****************************************************************************
  1345. +**
  1346. +** Copyright (C) 2020 Klaralvdalens Datakonsult AB (KDAB).
  1347. +** Contact: https://www.qt.io/licensing/
  1348. +**
  1349. +** This file is part of the Qt3D module of the Qt Toolkit.
  1350. +**
  1351. +** $QT_BEGIN_LICENSE:LGPL$
  1352. +** Commercial License Usage
  1353. +** Licensees holding valid commercial Qt licenses may use this file in
  1354. +** accordance with the commercial license agreement provided with the
  1355. +** Software or, alternatively, in accordance with the terms contained in
  1356. +** a written agreement between you and The Qt Company. For licensing terms
  1357. +** and conditions see https://www.qt.io/terms-conditions. For further
  1358. +** information use the contact form at https://www.qt.io/contact-us.
  1359. +**
  1360. +** GNU Lesser General Public License Usage
  1361. +** Alternatively, this file may be used under the terms of the GNU Lesser
  1362. +** General Public License version 3 as published by the Free Software
  1363. +** Foundation and appearing in the file LICENSE.LGPL3 included in the
  1364. +** packaging of this file. Please review the following information to
  1365. +** ensure the GNU Lesser General Public License version 3 requirements
  1366. +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
  1367. +**
  1368. +** GNU General Public License Usage
  1369. +** Alternatively, this file may be used under the terms of the GNU
  1370. +** General Public License version 2.0 or (at your option) the GNU General
  1371. +** Public license version 3 or any later version approved by the KDE Free
  1372. +** Qt Foundation. The licenses are as published by the Free Software
  1373. +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
  1374. +** included in the packaging of this file. Please review the following
  1375. +** information to ensure the GNU General Public License requirements will
  1376. +** be met: https://www.gnu.org/licenses/gpl-2.0.html and
  1377. +** https://www.gnu.org/licenses/gpl-3.0.html.
  1378. +**
  1379. +** $QT_END_LICENSE$
  1380. +**
  1381. +****************************************************************************/
  1382. +
  1383. +#ifndef QT3DCORE_JOB_COMMON_P_H
  1384. +#define QT3DCORE_JOB_COMMON_P_H
  1385. +
  1386. +//
  1387. +// W A R N I N G
  1388. +// -------------
  1389. +//
  1390. +// This file is not part of the Qt API. It exists purely as an
  1391. +// implementation detail. This header file may change from version to
  1392. +// version without notice, or even be removed.
  1393. +//
  1394. +// We mean it.
  1395. +//
  1396. +
  1397. +#include <Qt3DCore/private/qaspectjob_p.h>
  1398. +
  1399. +QT_BEGIN_NAMESPACE
  1400. +
  1401. +namespace Qt3DCore {
  1402. +
  1403. +namespace JobTypes {
  1404. +
  1405. + enum JobType {
  1406. + LoadBuffer = 4096,
  1407. + CalcBoundingVolume,
  1408. + };
  1409. +
  1410. +} // JobTypes
  1411. +
  1412. +} // Qt3DCore
  1413. +
  1414. +QT_END_NAMESPACE
  1415. +
  1416. +#endif // QT3DCORE_JOB_COMMON_P_H
  1417. diff --git a/src/core/jobs/jobs.pri b/src/core/jobs/jobs.pri
  1418. index 5d262f5..a045339 100644 (file)
  1419. --- a/src/core/jobs/jobs.pri
  1420. +++ b/src/core/jobs/jobs.pri
  1421. @@ -4,7 +4,8 @@ SOURCES += \
  1422. $$PWD/qaspectjobmanager.cpp \
  1423. $$PWD/qabstractaspectjobmanager.cpp \
  1424. $$PWD/qthreadpooler.cpp \
  1425. - $$PWD/task.cpp
  1426. + $$PWD/task.cpp \
  1427. + $$PWD/calcboundingvolumejob.cpp
  1428. HEADERS += \
  1429. $$PWD/qaspectjob.h \
  1430. @@ -13,7 +14,9 @@ HEADERS += \
  1431. $$PWD/qaspectjobmanager_p.h \
  1432. $$PWD/qabstractaspectjobmanager_p.h \
  1433. $$PWD/task_p.h \
  1434. - $$PWD/qthreadpooler_p.h
  1435. + $$PWD/qthreadpooler_p.h \
  1436. + $$PWD/calcboundingvolumejob_p.h \
  1437. + $$PWD/job_common_p.h
  1438. INCLUDEPATH += $$PWD