8#include <private/qquick3dobject_p.h>
47 return m_segmentCount;
75 return m_scaleMultiplier;
86 return m_texcoordMultiplier;
111 return m_lengthVariation;
122 return m_lengthDeltaMin;
134 return m_eolFadeOutDuration;
157 return m_texcoordMode;
163 if (m_segmentCount ==
count)
165 m_segmentCount =
count;
166 handleSegmentCountChanged();
172 fade =
qBound(0.0f, fade, 1.0f);
181 multiplier =
qBound(0.0f, multiplier, 2.0f);
184 m_scaleMultiplier = multiplier;
192 m_texcoordMultiplier = multiplier;
216 min =
qMax(min, 0.0f);
219 m_lengthDeltaMin = min;
225 duration =
qMax(0, duration);
226 if (duration == m_eolFadeOutDuration)
228 m_eolFadeOutDuration = duration;
234 if (
mode == m_texcoordMode)
236 m_texcoordMode =
mode;
268 particles->m_alphaFade = 1.0f - m_alphaFade;
270 particles->m_texcoordScale = frames * m_texcoordMultiplier;
272 particles->m_texcoordScale = frames /
particleScale() * m_texcoordMultiplier;
280 if (m_lineData.size() == amount)
283 m_lineData.resize(m_segmentCount * amount);
284 m_lineHeaderData.resize(amount);
291 delete value.particleUpdateNode;
292 value.particleUpdateNode =
new LineParticleUpdateNode(
system);
293 value.particleUpdateNode->m_particle =
this;
302 lineParticle->updateLineNode(node);
307 lineParticle->updateLineBuffer(
this, particles);
314void QQuick3DParticleLineParticle ::reset()
318 m_lineHeaderData.fill({});
319 m_fadeOutData.clear();
326 for (
auto iter = m_fadeOutData.begin();
iter != m_fadeOutData.end(); ) {
327 if (
time >=
iter->beginTime && time < iter->endTime)
339 perEmitter.particleUpdateNode =
new LineParticleUpdateNode(
system());
340 perEmitter.emitter = emitter;
341 perEmitter.particleUpdateNode->m_particle =
this;
348 m_lineHeaderData[
index].length =
qMax(0.0f, m_length + m_lengthVariation * (
system()->rand()->
get(
index) - 0.5f));
356 float size,
float age,
357 float animationFrame)
363 updateLineSegment(particleIndex);
368 LineDataHeader *
header = m_lineHeaderData.data() + particleIndex;
376void QQuick3DParticleLineParticle::saveLineSegment(
int particleIndex,
float time)
378 if (m_eolFadeOutDuration > 0 && m_lineHeaderData[particleIndex].pointCount > 0) {
379 FadeOutLineData
data;
382 data.endTime =
time + m_eolFadeOutDuration * 0.001f;
383 data.timeFactor = 1000.0f / ((float)m_eolFadeOutDuration);
384 data.header = m_lineHeaderData[particleIndex];
385 data.lineData = m_lineData.mid(particleIndex * m_segmentCount, m_segmentCount);
387 m_fadeOutData.emplaceBack(
data);
388 clearSegment(particleIndex);
405void QQuick3DParticleLineParticle::updateLineBuffer(LineParticleUpdateNode *updateNode,
QSSGRenderGraphObject *spatialNode)
413 for (
int i = 0;
i < m_lineHeaderData.size();
i++) {
414 if (m_lineHeaderData[
i].pointCount && m_lineHeaderData[
i].emitterIndex == perEmitter.emitterIndex)
417 int totalCount = lineCount;
419 for (
int i = 0;
i < m_fadeOutData.size();
i++) {
420 if (m_fadeOutData[
i].emitterIndex == perEmitter.emitterIndex)
424 totalCount += m_fadeOutData.size();
430 if (!totalCount)
return;
432 const int segments = m_segmentCount;
435 int sliceParticleIdx = 0;
440 const LineDataHeader *
header = m_lineHeaderData.constData();
441 const LineData *lineData = m_lineData.constData();
444 auto nextParticle = [](
char *&
buffer,
int &slice,
int &sliceParticleIdx,
int particlesPerSlice,
int sliceStride) ->
QSSGLineParticle* {
447 if (sliceParticleIdx == particlesPerSlice) {
450 sliceParticleIdx = 0;
455 auto genLine = [&](
const SpriteParticleData &sdata,
const LineDataHeader &
header,
const LineData *tdata,
457 char *&
buffer,
int &slice,
int &sliceParticleIdx,
int particlesPerSlice,
int sliceStride,
bool absolute,
bool fill) {
458 QSSGLineParticle *particle = nextParticle(
buffer, slice, sliceParticleIdx, particlesPerSlice, sliceStride);
459 int idx =
header.currentIndex;
460 particle->
color = sdata.color;
465 particle->
position = sdata.position;
466 particle->
age = sdata.age;
469 float partialLength = (tdata[idx].position - sdata.position).
length();
470 float length0 = tdata[idx].length + partialLength;
474 float lengthScale = -1.0f;
477 particle->
length = length0;
482 if (lineLength > 0.0f) {
483 lengthScale = -1.0f / lineLength;
485 float totalLength = tdata[idx].length - tdata[lastIdx].length;
487 totalLength += partialLength;
489 lengthScale = -1.0f / totalLength;
492 bounds.include(sdata.position);
500 float totalLength = 0;
501 float prevLength = tdata[idx].length + partialLength;
502 for (segmentIdx = 0; segmentIdx <
header.pointCount && totalLength <
header.
length; segmentIdx++) {
503 particle = nextParticle(
buffer, slice, sliceParticleIdx, particlesPerSlice, sliceStride);
505 if (particle->
size > 0.0f) {
506 bounds.include(tdata[idx].
position);
507 particle->
color = tdata[idx].color;
509 particle->
binormal = tdata[idx].binormal;
510 particle->
position = tdata[idx].position;
512 particle->
age = sdata.age;
513 particle->
length = (length0 - tdata[idx].length) * lengthScale;
514 float segmentLength = prevLength - tdata[idx].length;
515 prevLength = tdata[idx].length;
517 float diff = totalLength + segmentLength -
header.
length;
518 particle->
position -= tdata[idx].tangent * diff;
519 particle->
length -= diff * lengthScale;
520 segmentLength -= diff;
522 totalLength += segmentLength;
526 idx = idx ? (idx - 1) : (
segments - 1);
529 for (segmentIdx = 0; segmentIdx <
header.pointCount; segmentIdx++) {
530 particle = nextParticle(
buffer, slice, sliceParticleIdx, particlesPerSlice, sliceStride);
532 if (particle->
size > 0.0f) {
533 bounds.include(tdata[idx].
position);
534 particle->
color = tdata[idx].color;
536 particle->
binormal = tdata[idx].binormal;
537 particle->
position = tdata[idx].position;
539 particle->
age = sdata.age;
540 particle->
length = (length0 - tdata[idx].length) * lengthScale;
544 idx = idx ? (idx - 1) : (
segments - 1);
547 for (;segmentIdx <
segments; segmentIdx++) {
548 particle = nextParticle(
buffer, slice, sliceParticleIdx, particlesPerSlice, sliceStride);
549 *particle = *prevGood;
550 particle->
size = 0.0f;
552 idx = idx ? (idx - 1) : (
segments - 1);
556 prevGood->
position -= tdata[prevIdx].tangent * partialLength;
558 prevGood->
length -= partialLength * lengthScale;
565 while (
i < lineCount) {
566 if (
header->pointCount &&
header->emitterIndex == perEmitter.emitterIndex) {
568 slice, sliceParticleIdx, particlesPerSlice, sliceStride, absolute,
fill);
577 for (
const FadeOutLineData &fdata : m_fadeOutData) {
578 if (fdata.emitterIndex == perEmitter.emitterIndex) {
579 float factor = 1.0f - (
time - fdata.beginTime) * fdata.timeFactor;
580 genLine(fdata.endPoint, fdata.header, fdata.lineData.data(), bounds,
segments,
581 particleScale(), factor, dest, slice, sliceParticleIdx, particlesPerSlice,
582 sliceStride, absolute,
fill);
588void QQuick3DParticleLineParticle::handleSegmentCountChanged()
594 m_lineHeaderData.fill({});
595 m_fadeOutData.clear();
603void QQuick3DParticleLineParticle::updateLineSegment(
int particleIndex)
605 if (m_lineData.isEmpty()) {
606 qWarning () <<
"Line particle updated before having been initialized";
609 LineDataHeader *
header = m_lineHeaderData.data() + particleIndex;
610 int idx =
header->currentIndex;
611 LineData *cur = m_lineData.data() + particleIndex * m_segmentCount;
612 LineData *prev =
header->pointCount ? cur + idx :
nullptr;
615 if (prev && m_segmentCount > 1) {
617 float minLength = m_lengthDeltaMin;
624 if (
header->pointCount < m_segmentCount)
628 idx = (idx + 1) % m_segmentCount;
629 header->currentIndex = idx;
632 cur->color =
src.color;
636 if (prev && m_segmentCount == 1) {
640 float minLength = m_lengthDeltaMin;
643 cur->position =
src.position + minLength *
t;
648 cur->position =
src.position;
652 if (prev && prev != cur) {
653 prev->tangent = prev->position -
src.position;
654 cur->length = prev->tangent.length();
655 prev->tangent /= cur->length;
656 cur->length += prev->length;
658 if (
header->pointCount == 1)
659 prev->binormal = cur->binormal;
661 prev->binormal = (prev->binormal + cur->binormal).
normalized();
665void QQuick3DParticleLineParticle::clearSegment(
int particleIndex)
667 if (m_lineData.isEmpty())
669 LineDataHeader *
header = m_lineHeaderData.data() + particleIndex;
671 auto data = m_lineData.begin() + particleIndex * m_segmentCount;
672 std::fill_n(
data, m_segmentCount, LineData());
674 header->emitterIndex = -1;
iterator insert(const Key &key, const T &value)
bool contains(const Key &key) const
QSSGRenderGraphObject * updateSpatialNode(QSSGRenderGraphObject *node) override
void lengthDeltaMinChanged()
void commitParticles(float time) override
void texcoordModeChanged()
void segmentCountChanged()
~QQuick3DParticleLineParticle() override
void handleMaxAmountChanged(int amount) override
void resetParticleData(int particleIndex) override
void texcoordMultiplierChanged()
int nextCurrentIndex(const QQuick3DParticleEmitter *emitter) override
void setLengthDeltaMin(float min)
void eolFadeOutDurationChanged()
QQuick3DParticleLineParticle(QQuick3DNode *parent=nullptr)
\qmltype LineParticle3D \inherits SpriteParticle3D \inqmlmodule QtQuick3D.Particles3D
void setLengthVariation(float length)
void setTexcoordMultiplier(float multiplier)
void setAlphaFade(float fade)
void scaleMultiplierChanged()
void lengthVariationChanged()
void setTexcoordMode(QQuick3DParticleLineParticle::TexcoordMode mode)
void setEolFadeOutDuration(int duration)
void setLength(float length)
void handleSystemChanged(QQuick3DParticleSystem *system) override
void setScaleMultiplier(float multiplier)
void setParticleData(int particleIndex, const QVector3D &position, const QVector3D &rotation, const QVector4D &color, float size, float age, float animationFrame) override
TexcoordMode texcoordMode
void setSegmentCount(int count)
virtual void setParticleData(int particleIndex, const QVector3D &position, const QVector3D &rotation, const QVector4D &color, float size, float age, float animationFrame)
virtual void commitParticles(float)
int nextCurrentIndex(const QQuick3DParticleEmitter *emitter) override
virtual void resetParticleData(int particleIndex)
QVector< SpriteParticleData > m_spriteParticleData
QMap< const QQuick3DParticleEmitter *, PerEmitterData > m_perEmitterData
PerEmitterData & perEmitterData(const QQuick3DNode *updateNode)
QSSGRenderGraphObject * updateParticleNode(const ParticleUpdateNode *updateNode, QSSGRenderGraphObject *node)
virtual void handleMaxAmountChanged(int amount)
QQuick3DParticleSpriteSequence * spriteSequence
FeatureLevel m_featureLevel
int currentTime() const
Returns the current time of the system (m_time + m_startTime).
QQuick3DParticleSystem * system() const
Class representing 3D range or axis aligned bounding box.
qsizetype size() const
Returns the number of characters in this string.
qsizetype length() const
Returns the number of characters in this string.
The QVector3D class represents a vector or vertex in 3D space.
float length() const noexcept
Returns the length of the vector from the origin.
constexpr float y() const noexcept
Returns the y coordinate of this point.
constexpr float x() const noexcept
Returns the x coordinate of this point.
static constexpr QVector3D crossProduct(QVector3D v1, QVector3D v2) noexcept
Returns the cross-product of vectors v1 and v2, which is normal to the plane spanned by v1 and v2.
The QVector4D class represents a vector or vertex in 4D space.
constexpr void setW(float w) noexcept
Sets the w coordinate of this point to the given finite w coordinate.
Combined button and popup list for selecting options.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter * iter
static QDBusError::ErrorType get(const char *name)
static QString header(const QString &name)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
bool qFuzzyIsNull(qfloat16 f) noexcept
constexpr float qDegreesToRadians(float degrees)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qBound(const T &min, const T &val, const T &max)
constexpr const T & qMax(const T &a, const T &b)
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLuint GLenum GLsizei length
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLenum GLboolean normalized
GLfloat GLfloat GLfloat alpha
QSSGRenderParticles::FeatureLevel lineFeatureLevel(QQuick3DParticleSpriteParticle::FeatureLevel in)
static QVector3D qt_normalFromRotation(const QVector3D &eulerRotation)
#define Q_QUICK3D_PROFILE_ASSIGN_ID_SG(obj, bgnode)
static qreal position(const QQuickItem *item, QQuickAnchors::Anchor anchorLine)
int particleCount() const
int particlesPerSlice() const
void setBounds(const QSSGBounds3 &bounds)
void resizeLine(int particleCount, int segmentCount)
QSSGParticleBuffer m_particleBuffer
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent