From cbcc886564805fc0995d20962c82981b8b05c0e3 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 17 Jan 2012 20:52:35 +1000 Subject: [PATCH] Add some internal docs for the particle system and sprite engine They're both large internal structures with extensive logic. Should have at least a basic attempt at documentation (beyond inline comments). Change-Id: I7d48ebf821fa759c11fa35889dbff8971644d23e Reviewed-by: Martin Jones --- src/quick/items/qquickspriteengine.cpp | 28 +++++++++++++++++++ src/quick/particles/qquickparticlesystem.cpp | 42 ++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/quick/items/qquickspriteengine.cpp b/src/quick/items/qquickspriteengine.cpp index 495957f..38be93f 100644 --- a/src/quick/items/qquickspriteengine.cpp +++ b/src/quick/items/qquickspriteengine.cpp @@ -48,6 +48,33 @@ QT_BEGIN_NAMESPACE +/* + \internal Stochastic/Sprite engine implementation docs + + Nomenclature: 'thing' refers to an instance of a running sprite or state. It could be renamed. + States and Transitions are referred to in the state machine sense here, NOT in the QML sense. + + The Stochastic State engine takes states with stochastic state transitions defined and transitions them. + When a state is started, it's added to a list of pending updates sorted by their time they want to update. + An external driver calls the update function with an elapsed time, which becomes the new time offset. + The pending update stack is popped until all entries are past the current time, which simulates all intervening time. + + The Sprite Engine subclass has two major differences. Firstly all states are sprites (and there's a new vector with them + cast to sprite). Secondly, it chops up images and states to fit a texture friendly format. + Before the Sprite Engine starts running, its user requests a texture assembled from all the sprite images. This + texture is made by pasting the sprites into one image, with one sprite animation per row (in the future it is planned to have + arbitrary X/Y start ends, but they will still be assembled and recorded here and still have to be contiguous lines). + This cut-up allows the users to calcuate frame positions with a texture percentage width and elapsed time. + It also means that large sprites cover multiple lines to fit inside the texture memory limit (which is a square). + + Large sprites covering multiple lines breaks this simple interface for the users, so each line is treated as a pseudostate + and it's mostly hidden from the spriteengine users (except that they'll get advanced signals where the state is the same + but the visual parameters changed). These are not real states because that would get very complex with bindings. Instead, + when sprite attributes are requested from a sprite that has multiple pseudostates, it returns the values for the psuedostate + it is in. State advancement is intercepted and hollow for pseudostates, except the last one. The last one transitions as the + state normally does. +*/ + /* TODO: make sharable? solve the state data initialization/transfer issue so as to not need to make friends @@ -337,6 +364,7 @@ QImage QQuickSpriteEngine::assembledImage() return image; } +//TODO: Add a reset() function, for completeness in the case of a SpriteEngine being restarted from 0 void QQuickStochasticEngine::setCount(int c) { m_things.resize(c); diff --git a/src/quick/particles/qquickparticlesystem.cpp b/src/quick/particles/qquickparticlesystem.cpp index 47aa4be..924a2d0 100644 --- a/src/quick/particles/qquickparticlesystem.cpp +++ b/src/quick/particles/qquickparticlesystem.cpp @@ -57,6 +57,48 @@ QT_BEGIN_NAMESPACE //###Switch to define later, for now user-friendly (no compilation) debugging is worth it DEFINE_BOOL_CONFIG_OPTION(qmlParticlesDebug, QML_PARTICLES_DEBUG) + + +/* \internal ParticleSystem internals documentation + + Affectors, Painters, Emitters and Groups all register themselves on construction as a callback + from their setSystem (or componentComplete if they have a system from a parent). + + Particle data is stored by group, They have a group index (used by the particle system almost + everywhere) and a global index (used by the Stochastic state engine powering stochastic group + transitions). Each group has a recycling list/heap that stores the particle data. + + The recycling list/heap is a heap of particle data sorted by when they're expected to die. If + they die prematurely then they are marked as reusable (and will probably still be alive when + they exit the heap). If they have their life extended, then they aren't dead when expected. + If this happens, they go back in the heap with the new estimate. If they have died on schedule, + then the indexes are marked as reusable. If no indexes are reusable when new particles are + requested, then the list is extended. This relatively complex datastructure is because memory + allocation and deallocation on this scale proved to be a significant performance cost. In order + to reuse the indexes validly (even when particles can have their life extended or cut short + dynamically, or particle counts grow) this seemed to be the most efficient option for keeping + track of which indices could be reused. + + When a new particle is emitted, the emitter gets a new datum from the group (through the + system), and sets properties on it. Then it's passed back to the group briefly so that it can + now guess when the particle will die. Then the painters get a change to initialize properties + as well, since particle data includes shared data from painters as well as logical particle + data. + + Every animation advance, the simulation advances by running all emitters for the elapsed + duration, then running all affectors, then telling all particle painters to update changed + particles. The ParticlePainter superclass stores these changes, and they are implemented + when the painter is called to paint in the render thread. + + Particle group changes move the particle from one group to another by killing the old particle + and then creating a new one with the same data in the new group. + + Note that currently groups only grow. Given that data is stored in vectors, it is non-trivial + to pluck out the unused indexes when the count goes down. Given the dynamic nature of the + system, it is difficult to tell if those unused data instances will be used again. Still, + some form of garbage collection is on the long term plan. +*/ + /*! \qmlclass ParticleSystem QQuickParticleSystem \inqmlmodule QtQuick.Particles 2 -- 2.7.4