10#include <QtQuick3DRuntimeRender/private/qssgrendergraphobject_p.h>
11#include <QtQuick3DRuntimeRender/private/qssgrendercustommaterial_p.h>
12#include <QtQuick3DRuntimeRender/private/qssgrenderdefaultmaterial_p.h>
13#include <QtQuick3DRuntimeRender/private/qssgrendermodel_p.h>
15#include <QtQuick3DUtils/private/qssgutils_p.h>
17#include <QtQml/QQmlFile>
116 qmlClearMaterials(&matList);
118 qmlClearMorphTargets(&morphList);
158 QQuick3DModel::qmlAppendMaterial,
159 QQuick3DModel::qmlMaterialsCount,
160 QQuick3DModel::qmlMaterialAt,
161 QQuick3DModel::qmlClearMaterials);
179 QQuick3DModel::qmlAppendMorphTarget,
180 QQuick3DModel::qmlMorphTargetsCount,
181 QQuick3DModel::qmlMorphTargetAt,
182 QQuick3DModel::qmlClearMorphTargets);
210 return m_instanceRoot;
220 if (
source.hasFragment()) {
233 return (qmlSource.isEmpty() ?
source.path() : qmlSource) + fragment;
238 m_dirtyAttributes = 0xffffffff;
254 return m_castsShadows;
272 return m_receivesShadows;
353 return m_inverseBindPoses;
393 return m_receivesReflections;
405 return m_castsReflections;
435bool QQuick3DModel::isUsedInBakedLighting()
const
437 return m_usedInBakedLighting;
474 return m_lightmapBaseResolution;
507 return m_bakedLightmap;
518 return m_instancingLodMin;
529 return m_instancingLodMax;
539 markDirty(SourceDirty);
551 markDirty(ShadowsDirty);
561 markDirty(ShadowsDirty);
566 if (m_pickable == isPickable)
569 m_pickable = isPickable;
571 markDirty(PickingDirty);
589 markDirty(GeometryDirty);
593 markDirty(GeometryDirty);
607 markDirty(SkeletonDirty);
620 markDirty(SkinDirty);
625 if (m_inverseBindPoses == poses)
628 m_inverseBindPoses = poses;
630 markDirty(PoseDirty);
656 this, [
this]{ markDirty(InstancesDirty);});
658 markDirty(InstancesDirty);
670 markDirty(InstanceRootDirty);
680 markDirty(PropertyDirty);
684void QQuick3DModel::setReceivesReflections(
bool receivesReflections)
690 emit receivesReflectionsChanged();
691 markDirty(ReflectionDirty);
694void QQuick3DModel::setCastsReflections(
bool castsReflections)
699 emit castsReflectionsChanged();
700 markDirty(ReflectionDirty);
703void QQuick3DModel::setUsedInBakedLighting(
bool enable)
705 if (m_usedInBakedLighting ==
enable)
708 m_usedInBakedLighting =
enable;
709 emit usedInBakedLightingChanged();
710 markDirty(PropertyDirty);
713void QQuick3DModel::setLightmapBaseResolution(
int resolution)
715 resolution =
qMax(128, resolution);
716 if (m_lightmapBaseResolution == resolution)
719 m_lightmapBaseResolution = resolution;
720 emit lightmapBaseResolutionChanged();
721 markDirty(PropertyDirty);
730 m_bakedLightmap->
disconnect(m_bakedLightmapSignalConnection);
735 [
this] { markDirty(PropertyDirty); });
740 m_bakedLightmap =
nullptr;
741 markDirty(PropertyDirty);
744 emit bakedLightmapChanged();
745 markDirty(PropertyDirty);
750 if (change == QQuick3DObject::ItemSceneChange)
751 updateSceneManager(
value.sceneManager);
762 int dirtyAttribute = 0;
765 if (m_dirtyAttributes & SourceDirty)
767 if (m_dirtyAttributes & PickingDirty)
770 if (m_dirtyAttributes & ShadowsDirty) {
771 modelNode->castsShadows = m_castsShadows;
772 modelNode->receivesShadows = m_receivesShadows;
775 if (m_dirtyAttributes & MaterialsDirty) {
776 if (!m_materials.isEmpty()) {
777 if (modelNode->materials.isEmpty()) {
779 for (
const Material &material : m_materials) {
782 modelNode->materials.append(graphObject);
784 dirtyAttribute |= MaterialsDirty;
788 if (modelNode->materials.size() != m_materials.size())
789 modelNode->materials.resize(m_materials.size());
790 for (
int i = 0;
i < m_materials.size(); ++
i) {
792 if (modelNode->materials[
i] != graphObject)
793 modelNode->materials[
i] = graphObject;
798 modelNode->materials.clear();
802 if (m_dirtyAttributes & MorphTargetsDirty) {
803 if (!m_morphTargets.isEmpty()) {
804 const int numMorphTarget = m_morphTargets.size();
805 if (modelNode->morphTargets.isEmpty()) {
807 for (
const auto morphTarget : std::as_const(m_morphTargets)) {
810 modelNode->morphTargets.append(graphObject);
812 dirtyAttribute |= MorphTargetsDirty;
814 modelNode->morphWeights.resize(numMorphTarget);
815 modelNode->morphAttributes.resize(numMorphTarget);
818 if (modelNode->morphTargets.size() != numMorphTarget) {
819 modelNode->morphTargets.resize(numMorphTarget);
820 modelNode->morphWeights.resize(numMorphTarget);
821 modelNode->morphAttributes.resize(numMorphTarget);
823 for (
int i = 0;
i < numMorphTarget; ++
i)
828 modelNode->morphTargets.clear();
832 if (m_dirtyAttributes &
quint32(InstancesDirty | InstanceRootDirty)) {
836 if (m_instanceRoot) {
837 if (m_instanceRoot ==
this)
838 instanceRootNode = modelNode;
850 modelNode->instanceTable =
nullptr;
854 if (m_dirtyAttributes & GeometryDirty) {
859 modelNode->geometry =
nullptr;
864 if (m_dirtyAttributes & SkeletonDirty) {
867 if (modelNode->skeleton)
870 modelNode->skeleton =
nullptr;
874 if (m_dirtyAttributes & SkinDirty) {
878 modelNode->skin =
nullptr;
881 if (m_dirtyAttributes & LodDirty) {
882 modelNode->instancingLodMin = m_instancingLodMin;
883 modelNode->instancingLodMax = m_instancingLodMax;
886 if (m_dirtyAttributes & PoseDirty) {
887 modelNode->inverseBindPoses = m_inverseBindPoses.
toVector();
888 if (modelNode->skeleton)
889 modelNode->skeleton->skinningDirty =
true;
892 if (m_dirtyAttributes & PropertyDirty) {
894 modelNode->usedInBakedLighting = m_usedInBakedLighting;
895 modelNode->lightmapBaseResolution =
uint(m_lightmapBaseResolution);
896 if (m_bakedLightmap && m_bakedLightmap->
isEnabled()) {
897 modelNode->lightmapKey = m_bakedLightmap->
key();
904 modelNode->lightmapKey.clear();
905 modelNode->lightmapLoadPath.clear();
907 modelNode->levelOfDetailBias = m_levelOfDetailBias;
910 if (m_dirtyAttributes & ReflectionDirty) {
911 modelNode->receivesReflections = m_receivesReflections;
912 modelNode->castsReflections = m_castsReflections;
915 m_dirtyAttributes = dirtyAttribute;
920void QQuick3DModel::markDirty(QQuick3DModel::QSSGModelDirtyType
type)
939 for (Material &mat : m_materials) {
952 for (Material &mat : m_materials) {
961void QQuick3DModel::onMaterialDestroyed(
QObject *
object)
964 for (
int i = 0;
i < m_materials.size(); ++
i) {
965 if (m_materials[
i].material ==
object) {
966 m_materials.removeAt(
i--);
971 markDirty(QQuick3DModel::MaterialsDirty);
976 if (material ==
nullptr)
980 self->markDirty(QQuick3DModel::MaterialsDirty);
982 if (material->parentItem() ==
nullptr) {
997 self->m_materials.
last().refed =
true;
1022 for (Material &mat :
self->m_materials) {
1023 if (mat.material->parentItem() ==
nullptr) {
1029 mat.material->disconnect(self,
SLOT(onMaterialDestroyed(
QObject*)));
1032 self->markDirty(QQuick3DModel::MaterialsDirty);
1035void QQuick3DModel::onMorphTargetDestroyed(
QObject *
object)
1038 for (
int i = 0;
i < m_morphTargets.size(); ++
i) {
1039 if (m_morphTargets.at(
i) ==
object) {
1040 m_morphTargets.removeAt(
i--);
1045 markDirty(QQuick3DModel::MorphTargetsDirty);
1046 m_numMorphAttribs = 0;
1052 if (morphTarget ==
nullptr)
1055 if (
self->m_numMorphAttribs >= 8) {
1056 qWarning(
"The number of morph attributes exceeds 8. This morph target will be ignored.");
1060 self->m_numMorphAttribs += morphTarget->numAttribs();
1061 if (
self->m_numMorphAttribs > 8)
1062 qWarning(
"The number of morph attributes exceeds 8. This morph target will be supported partially.");
1064 self->markDirty(QQuick3DModel::MorphTargetsDirty);
1066 if (morphTarget->parentItem() ==
nullptr) {
1088 qWarning(
"The index exceeds the range of valid morph targets.");
1097 return self->m_morphTargets.
size();
1103 for (
const auto &morph :
std::as_const(
self->m_morphTargets)) {
1104 if (morph->parentItem() ==
nullptr)
1106 morph->disconnect(self,
SLOT(onMorphTargetDestroyed(
QObject*)));
1109 self->m_numMorphAttribs = 0;
1110 self->markDirty(QQuick3DModel::MorphTargetsDirty);
1113void QQuick3DModel::setInstancingLodMin(
float minDistance)
1117 m_instancingLodMin = minDistance;
1118 emit instancingLodMinChanged();
1119 markDirty(LodDirty);
1122void QQuick3DModel::setInstancingLodMax(
float maxDistance)
1126 m_instancingLodMax = maxDistance;
1127 emit instancingLodMaxChanged();
1128 markDirty(LodDirty);
1157 return m_levelOfDetailBias;
1160void QQuick3DModel::setLevelOfDetailBias(
float newLevelOfDetailBias)
1162 if (
qFuzzyCompare(m_levelOfDetailBias, newLevelOfDetailBias))
1164 m_levelOfDetailBias = newLevelOfDetailBias;
1165 emit levelOfDetailBiasChanged();
1166 markDirty(QQuick3DModel::PropertyDirty);
QList< T > toVector() const noexcept
void append(parameter_type t)
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
void destroyed(QObject *=nullptr)
This signal is emitted immediately before the object obj is destroyed, after any instances of QPointe...
The QQmlContext class defines a context within a QML engine.
static QString urlToLocalFileOrQrc(const QString &)
If url is a local file returns a path suitable for passing to QFile.
The QQmlListProperty class allows applications to expose list-like properties of QObject-derived clas...
bool isEnabled() const
\qmltype BakedLightmap \inherits Object \inqmlmodule QtQuick3D
\qmltype Geometry \inherits Object3D \inqmlmodule QtQuick3D \instantiates QQuick3DGeometry
int const QVector3D const QVector3D & boundsMax
Returns the maximum coordinate of the bounding volume.
int const QVector3D & boundsMin
Returns the minimum coordinate of the bounding volume.
\inmodule QtQuick3D \inherits QQuick3DObject
void receivesShadowsChanged()
bool castsReflections
\qmlproperty bool Model::castsReflections
QQuick3DBakedLightmap * bakedLightmap
\qmlproperty BakedLightmap Model::bakedLightmap
QQuick3DGeometry * geometry
static QString translateMeshSource(const QUrl &source, QObject *contextObject)
QSSGRenderGraphObject * updateSpatialNode(QSSGRenderGraphObject *node) override
QQmlListProperty< QQuick3DMaterial > materials
\qmlproperty List<QtQuick3D::Material> Model::materials
void instanceRootChanged()
QQuick3DSkeleton * skeleton
float instancingLodMin
\qmlproperty real Model::instancingLodMin
void setPickable(bool pickable)
void setCastsShadows(bool castsShadows)
void setInverseBindPoses(const QList< QMatrix4x4 > &poses)
void setInstanceRoot(QQuick3DNode *instanceRoot)
void castsShadowsChanged()
float levelOfDetailBias
\qmlproperty real Model::levelOfDetailBias
QQmlListProperty< QQuick3DMorphTarget > morphTargets
\qmlproperty List<QtQuick3D::MorphTarget> Model::morphTargets
void itemChange(ItemChange, const ItemChangeData &) override
void setInstancing(QQuick3DInstancing *instancing)
QQuick3DModel(QQuick3DNode *parent=nullptr)
\qmltype Model \inherits Node \inqmlmodule QtQuick3D
float instancingLodMax
\qmlproperty real Model::instancingLodMax
void inverseBindPosesChanged()
QQuick3DSkin * skin
\qmlproperty Skin Model::skin
void setGeometry(QQuick3DGeometry *geometry)
void setDepthBias(float bias)
QList< QMatrix4x4 > inverseBindPoses
void setReceivesShadows(bool receivesShadows)
void setBounds(const QVector3D &min, const QVector3D &max)
QQuick3DNode * instanceRoot
void setSkeleton(QQuick3DSkeleton *skeleton)
QQuick3DInstancing * instancing
void setSource(const QUrl &source)
int lightmapBaseResolution
\qmlproperty int Model::lightmapBaseResolution
void markAllDirty() override
bool receivesReflections
\qmlproperty bool Model::receivesReflections
~QQuick3DModel() override
void markAllDirty() override
QSSGRenderGraphObject * updateSpatialNode(QSSGRenderGraphObject *node) override
QPointer< QQuick3DSceneManager > sceneManager
void refSceneManager(QQuick3DSceneManager &)
static QQuick3DObjectPrivate * get(QQuick3DObject *item)
QSSGRenderGraphObject * spatialNode
static void attachWatcher(Context *context, Setter setter, Object3D *newO, Object3D *oldO)
Attach a object-destroyed-watcher to an object that's not owned.
\qmltype Object3D \inqmlmodule QtQuick3D \instantiates QQuick3DObject \inherits QtObject
QQuick3DObject * parent
\qmlproperty Object3D QtQuick3D::Object3D::parent This property holds the parent of the Object3D in a...
void setParentItem(QQuick3DObject *parentItem)
QList< QQuick3DObject * > dirtyBoundingBoxList
Class representing 3D range or axis aligned bounding box.
\macro QT_RESTRICTED_CAST_FROM_ASCII
QString last(qsizetype n) const
void clear()
Clears the contents of the string and makes it null.
qsizetype size() const
Returns the number of characters in this string.
void push_back(QChar c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
The QVector3D class represents a vector or vertex in 3D space.
Combined button and popup list for selecting options.
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
constexpr const T & qMax(const T &a, const T &b)
static bool isNumber(char s)
GLsizei GLsizei GLchar * source
QQmlContext * qmlContext(const QObject *obj)
static QUrl resolvedUrl(const QUrl &url, const QQmlRefPointer< QQmlContextData > &context)
#define QStringLiteral(str)
myObject disconnect()
[26]
static float signedSquared(float val)
void markDirty(DirtyFlag dirtyFlag)
QSSGRenderNode * instanceRoot
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent