Experimental Particle System
This adds a new "Particles" slide to viewer, that allows
editing, loading, and saving particle effects. All of the
particle system code is in modules/particles.
There are many rough edges and some not-yet-finished changes
to generalize the model[1]. A rough overview:
- SkReflected.h implements a lightweight reflection system
for classes derived from SkReflected. Adding a new class
involves deriving from SkReflected, adding a macro to the
class declaration, and implementing visitFields(), which
simply calls a virtual on an SkFieldVisitor for each field.
Currently, emitters and affectors use this mechanism.
- SkParticleSerialization.h demonstrates two useful field
visitors - for serializing to and from JSON. The driver
code that uses those is directly in ParticlesSlide.
- SkParticleData.h and SkCurve.h define a variety of helper
types for talking about particles, both for parameterizing
individual values, and communicating about the state of a
particle among the effect, affectors, and emitters.
- SkParticleEffect.h defines the static data definition of
an effect (SkParticleEffectParams), as well as a running
instance of an effect (SkParticleEffect). The effect has
simple update() and draw() methods.
- ParticlesSlide.cpp adds a third field visitor to generate
GUIs for interactively editing the running effect.
---
1: The critical change I'd like to make is to remove all
special case behavior over time and at spawn (setting sprite
frames, size over time, color over time, etc...). Integration
is the only fixed function behavior. Everything else is driven
by two lists of affectors. One is applied at spawn time, using
the effect's lifetime to evaluate curves. This allows spawning
particles with different colors as the effect ages out, for
example. The second list is applied every frame to update
existing particles, and is driven by the particle's lifetime.
This allows particles to change color after being spawned, for
example.
With a small set of affectors using a single expressive curve
primitive (keyframed list of cubic curve segments), we can
have affectors that update color, size, velocity, position,
sprite frame, etc., and implement many complex behaviors.
Bug: skia:
Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4
Reviewed-on: https://skia-review.googlesource.com/c/181404
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2019 Google LLC
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef SkCurve_DEFINED
|
|
|
|
#define SkCurve_DEFINED
|
|
|
|
|
2019-02-20 17:25:20 +00:00
|
|
|
#include "SkColor.h"
|
2019-03-04 15:55:22 +00:00
|
|
|
#include "SkParticleData.h"
|
Experimental Particle System
This adds a new "Particles" slide to viewer, that allows
editing, loading, and saving particle effects. All of the
particle system code is in modules/particles.
There are many rough edges and some not-yet-finished changes
to generalize the model[1]. A rough overview:
- SkReflected.h implements a lightweight reflection system
for classes derived from SkReflected. Adding a new class
involves deriving from SkReflected, adding a macro to the
class declaration, and implementing visitFields(), which
simply calls a virtual on an SkFieldVisitor for each field.
Currently, emitters and affectors use this mechanism.
- SkParticleSerialization.h demonstrates two useful field
visitors - for serializing to and from JSON. The driver
code that uses those is directly in ParticlesSlide.
- SkParticleData.h and SkCurve.h define a variety of helper
types for talking about particles, both for parameterizing
individual values, and communicating about the state of a
particle among the effect, affectors, and emitters.
- SkParticleEffect.h defines the static data definition of
an effect (SkParticleEffectParams), as well as a running
instance of an effect (SkParticleEffect). The effect has
simple update() and draw() methods.
- ParticlesSlide.cpp adds a third field visitor to generate
GUIs for interactively editing the running effect.
---
1: The critical change I'd like to make is to remove all
special case behavior over time and at spawn (setting sprite
frames, size over time, color over time, etc...). Integration
is the only fixed function behavior. Everything else is driven
by two lists of affectors. One is applied at spawn time, using
the effect's lifetime to evaluate curves. This allows spawning
particles with different colors as the effect ages out, for
example. The second list is applied every frame to update
existing particles, and is driven by the particle's lifetime.
This allows particles to change color after being spawned, for
example.
With a small set of affectors using a single expressive curve
primitive (keyframed list of cubic curve segments), we can
have affectors that update color, size, velocity, position,
sprite frame, etc., and implement many complex behaviors.
Bug: skia:
Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4
Reviewed-on: https://skia-review.googlesource.com/c/181404
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
|
|
|
#include "SkScalar.h"
|
2019-02-14 21:55:21 +00:00
|
|
|
#include "SkTArray.h"
|
Experimental Particle System
This adds a new "Particles" slide to viewer, that allows
editing, loading, and saving particle effects. All of the
particle system code is in modules/particles.
There are many rough edges and some not-yet-finished changes
to generalize the model[1]. A rough overview:
- SkReflected.h implements a lightweight reflection system
for classes derived from SkReflected. Adding a new class
involves deriving from SkReflected, adding a macro to the
class declaration, and implementing visitFields(), which
simply calls a virtual on an SkFieldVisitor for each field.
Currently, emitters and affectors use this mechanism.
- SkParticleSerialization.h demonstrates two useful field
visitors - for serializing to and from JSON. The driver
code that uses those is directly in ParticlesSlide.
- SkParticleData.h and SkCurve.h define a variety of helper
types for talking about particles, both for parameterizing
individual values, and communicating about the state of a
particle among the effect, affectors, and emitters.
- SkParticleEffect.h defines the static data definition of
an effect (SkParticleEffectParams), as well as a running
instance of an effect (SkParticleEffect). The effect has
simple update() and draw() methods.
- ParticlesSlide.cpp adds a third field visitor to generate
GUIs for interactively editing the running effect.
---
1: The critical change I'd like to make is to remove all
special case behavior over time and at spawn (setting sprite
frames, size over time, color over time, etc...). Integration
is the only fixed function behavior. Everything else is driven
by two lists of affectors. One is applied at spawn time, using
the effect's lifetime to evaluate curves. This allows spawning
particles with different colors as the effect ages out, for
example. The second list is applied every frame to update
existing particles, and is driven by the particle's lifetime.
This allows particles to change color after being spawned, for
example.
With a small set of affectors using a single expressive curve
primitive (keyframed list of cubic curve segments), we can
have affectors that update color, size, velocity, position,
sprite frame, etc., and implement many complex behaviors.
Bug: skia:
Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4
Reviewed-on: https://skia-review.googlesource.com/c/181404
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
|
|
|
|
|
|
|
class SkFieldVisitor;
|
|
|
|
|
2019-02-19 20:39:18 +00:00
|
|
|
/**
|
|
|
|
* SkCurve implements a keyframed 1D function, useful for animating values over time. This pattern
|
|
|
|
* is common in digital content creation tools. An SkCurve might represent rotation, scale, opacity,
|
|
|
|
* or any other scalar quantity.
|
|
|
|
*
|
|
|
|
* An SkCurve has a logical domain of [0, 1], and is made of one or more SkCurveSegments.
|
|
|
|
* Each segment describes the behavior of the curve in some sub-domain. For an SkCurve with N
|
|
|
|
* segments, there are (N - 1) intermediate x-values that subdivide the domain. The first and last
|
|
|
|
* x-values are implicitly 0 and 1:
|
|
|
|
*
|
|
|
|
* 0 ... x[0] ... x[1] ... ... 1
|
|
|
|
* Segment_0 Segment_1 ... Segment_N-1
|
|
|
|
*
|
|
|
|
* Each segment describes a function over [0, 1] - x-values are re-normalized to the segment's
|
|
|
|
* domain when being evaluated. The segments are cubic polynomials, defined by four values (fMin).
|
|
|
|
* These are the values at x=0 and x=1, as well as control points at x=1/3 and x=2/3.
|
|
|
|
*
|
|
|
|
* For segments with fConstant == true, only the first value is used (fMin[0]).
|
|
|
|
*
|
|
|
|
* Each segment has two additional features for creating interesting (and varied) animation:
|
|
|
|
* - A segment can be ranged. Ranged segments have two sets of coefficients, and a random value
|
2019-03-06 21:56:58 +00:00
|
|
|
* taken from the particle's SkRandom is used to lerp betwen them. Typically, the SkRandom is
|
|
|
|
* in the same state at each call, so this value is stable. That causes a ranged SkCurve to
|
|
|
|
* produce a single smooth cubic function somewhere within the range defined by fMin and fMax.
|
2019-02-19 20:39:18 +00:00
|
|
|
* - A segment can be bidirectional. In that case, after a value is computed, it will be negated
|
|
|
|
* 50% of the time.
|
|
|
|
*/
|
|
|
|
|
2019-02-27 16:19:19 +00:00
|
|
|
enum SkCurveSegmentType {
|
|
|
|
kConstant_SegmentType,
|
|
|
|
kLinear_SegmentType,
|
|
|
|
kCubic_SegmentType,
|
|
|
|
};
|
|
|
|
|
2019-02-14 21:55:21 +00:00
|
|
|
struct SkCurveSegment {
|
2019-02-25 19:15:02 +00:00
|
|
|
SkScalar eval(SkScalar x, SkScalar t, bool negate) const;
|
2019-02-14 21:55:21 +00:00
|
|
|
void visitFields(SkFieldVisitor* v);
|
Experimental Particle System
This adds a new "Particles" slide to viewer, that allows
editing, loading, and saving particle effects. All of the
particle system code is in modules/particles.
There are many rough edges and some not-yet-finished changes
to generalize the model[1]. A rough overview:
- SkReflected.h implements a lightweight reflection system
for classes derived from SkReflected. Adding a new class
involves deriving from SkReflected, adding a macro to the
class declaration, and implementing visitFields(), which
simply calls a virtual on an SkFieldVisitor for each field.
Currently, emitters and affectors use this mechanism.
- SkParticleSerialization.h demonstrates two useful field
visitors - for serializing to and from JSON. The driver
code that uses those is directly in ParticlesSlide.
- SkParticleData.h and SkCurve.h define a variety of helper
types for talking about particles, both for parameterizing
individual values, and communicating about the state of a
particle among the effect, affectors, and emitters.
- SkParticleEffect.h defines the static data definition of
an effect (SkParticleEffectParams), as well as a running
instance of an effect (SkParticleEffect). The effect has
simple update() and draw() methods.
- ParticlesSlide.cpp adds a third field visitor to generate
GUIs for interactively editing the running effect.
---
1: The critical change I'd like to make is to remove all
special case behavior over time and at spawn (setting sprite
frames, size over time, color over time, etc...). Integration
is the only fixed function behavior. Everything else is driven
by two lists of affectors. One is applied at spawn time, using
the effect's lifetime to evaluate curves. This allows spawning
particles with different colors as the effect ages out, for
example. The second list is applied every frame to update
existing particles, and is driven by the particle's lifetime.
This allows particles to change color after being spawned, for
example.
With a small set of affectors using a single expressive curve
primitive (keyframed list of cubic curve segments), we can
have affectors that update color, size, velocity, position,
sprite frame, etc., and implement many complex behaviors.
Bug: skia:
Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4
Reviewed-on: https://skia-review.googlesource.com/c/181404
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
|
|
|
|
2019-02-14 21:55:21 +00:00
|
|
|
void setConstant(SkScalar c) {
|
2019-02-27 16:19:19 +00:00
|
|
|
fType = kConstant_SegmentType;
|
|
|
|
fRanged = false;
|
2019-02-14 21:55:21 +00:00
|
|
|
fMin[0] = c;
|
Experimental Particle System
This adds a new "Particles" slide to viewer, that allows
editing, loading, and saving particle effects. All of the
particle system code is in modules/particles.
There are many rough edges and some not-yet-finished changes
to generalize the model[1]. A rough overview:
- SkReflected.h implements a lightweight reflection system
for classes derived from SkReflected. Adding a new class
involves deriving from SkReflected, adding a macro to the
class declaration, and implementing visitFields(), which
simply calls a virtual on an SkFieldVisitor for each field.
Currently, emitters and affectors use this mechanism.
- SkParticleSerialization.h demonstrates two useful field
visitors - for serializing to and from JSON. The driver
code that uses those is directly in ParticlesSlide.
- SkParticleData.h and SkCurve.h define a variety of helper
types for talking about particles, both for parameterizing
individual values, and communicating about the state of a
particle among the effect, affectors, and emitters.
- SkParticleEffect.h defines the static data definition of
an effect (SkParticleEffectParams), as well as a running
instance of an effect (SkParticleEffect). The effect has
simple update() and draw() methods.
- ParticlesSlide.cpp adds a third field visitor to generate
GUIs for interactively editing the running effect.
---
1: The critical change I'd like to make is to remove all
special case behavior over time and at spawn (setting sprite
frames, size over time, color over time, etc...). Integration
is the only fixed function behavior. Everything else is driven
by two lists of affectors. One is applied at spawn time, using
the effect's lifetime to evaluate curves. This allows spawning
particles with different colors as the effect ages out, for
example. The second list is applied every frame to update
existing particles, and is driven by the particle's lifetime.
This allows particles to change color after being spawned, for
example.
With a small set of affectors using a single expressive curve
primitive (keyframed list of cubic curve segments), we can
have affectors that update color, size, velocity, position,
sprite frame, etc., and implement many complex behaviors.
Bug: skia:
Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4
Reviewed-on: https://skia-review.googlesource.com/c/181404
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
|
|
|
}
|
|
|
|
|
2019-02-14 21:55:21 +00:00
|
|
|
SkScalar fMin[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
|
|
|
SkScalar fMax[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
Experimental Particle System
This adds a new "Particles" slide to viewer, that allows
editing, loading, and saving particle effects. All of the
particle system code is in modules/particles.
There are many rough edges and some not-yet-finished changes
to generalize the model[1]. A rough overview:
- SkReflected.h implements a lightweight reflection system
for classes derived from SkReflected. Adding a new class
involves deriving from SkReflected, adding a macro to the
class declaration, and implementing visitFields(), which
simply calls a virtual on an SkFieldVisitor for each field.
Currently, emitters and affectors use this mechanism.
- SkParticleSerialization.h demonstrates two useful field
visitors - for serializing to and from JSON. The driver
code that uses those is directly in ParticlesSlide.
- SkParticleData.h and SkCurve.h define a variety of helper
types for talking about particles, both for parameterizing
individual values, and communicating about the state of a
particle among the effect, affectors, and emitters.
- SkParticleEffect.h defines the static data definition of
an effect (SkParticleEffectParams), as well as a running
instance of an effect (SkParticleEffect). The effect has
simple update() and draw() methods.
- ParticlesSlide.cpp adds a third field visitor to generate
GUIs for interactively editing the running effect.
---
1: The critical change I'd like to make is to remove all
special case behavior over time and at spawn (setting sprite
frames, size over time, color over time, etc...). Integration
is the only fixed function behavior. Everything else is driven
by two lists of affectors. One is applied at spawn time, using
the effect's lifetime to evaluate curves. This allows spawning
particles with different colors as the effect ages out, for
example. The second list is applied every frame to update
existing particles, and is driven by the particle's lifetime.
This allows particles to change color after being spawned, for
example.
With a small set of affectors using a single expressive curve
primitive (keyframed list of cubic curve segments), we can
have affectors that update color, size, velocity, position,
sprite frame, etc., and implement many complex behaviors.
Bug: skia:
Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4
Reviewed-on: https://skia-review.googlesource.com/c/181404
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
|
|
|
|
2019-02-27 16:19:19 +00:00
|
|
|
int fType = kConstant_SegmentType;
|
2019-02-14 21:55:21 +00:00
|
|
|
bool fRanged = false;
|
|
|
|
bool fBidirectional = false;
|
Experimental Particle System
This adds a new "Particles" slide to viewer, that allows
editing, loading, and saving particle effects. All of the
particle system code is in modules/particles.
There are many rough edges and some not-yet-finished changes
to generalize the model[1]. A rough overview:
- SkReflected.h implements a lightweight reflection system
for classes derived from SkReflected. Adding a new class
involves deriving from SkReflected, adding a macro to the
class declaration, and implementing visitFields(), which
simply calls a virtual on an SkFieldVisitor for each field.
Currently, emitters and affectors use this mechanism.
- SkParticleSerialization.h demonstrates two useful field
visitors - for serializing to and from JSON. The driver
code that uses those is directly in ParticlesSlide.
- SkParticleData.h and SkCurve.h define a variety of helper
types for talking about particles, both for parameterizing
individual values, and communicating about the state of a
particle among the effect, affectors, and emitters.
- SkParticleEffect.h defines the static data definition of
an effect (SkParticleEffectParams), as well as a running
instance of an effect (SkParticleEffect). The effect has
simple update() and draw() methods.
- ParticlesSlide.cpp adds a third field visitor to generate
GUIs for interactively editing the running effect.
---
1: The critical change I'd like to make is to remove all
special case behavior over time and at spawn (setting sprite
frames, size over time, color over time, etc...). Integration
is the only fixed function behavior. Everything else is driven
by two lists of affectors. One is applied at spawn time, using
the effect's lifetime to evaluate curves. This allows spawning
particles with different colors as the effect ages out, for
example. The second list is applied every frame to update
existing particles, and is driven by the particle's lifetime.
This allows particles to change color after being spawned, for
example.
With a small set of affectors using a single expressive curve
primitive (keyframed list of cubic curve segments), we can
have affectors that update color, size, velocity, position,
sprite frame, etc., and implement many complex behaviors.
Bug: skia:
Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4
Reviewed-on: https://skia-review.googlesource.com/c/181404
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
|
|
|
};
|
|
|
|
|
2019-02-14 21:55:21 +00:00
|
|
|
struct SkCurve {
|
|
|
|
SkCurve(SkScalar c = 0.0f) {
|
|
|
|
fSegments.push_back().setConstant(c);
|
|
|
|
}
|
Experimental Particle System
This adds a new "Particles" slide to viewer, that allows
editing, loading, and saving particle effects. All of the
particle system code is in modules/particles.
There are many rough edges and some not-yet-finished changes
to generalize the model[1]. A rough overview:
- SkReflected.h implements a lightweight reflection system
for classes derived from SkReflected. Adding a new class
involves deriving from SkReflected, adding a macro to the
class declaration, and implementing visitFields(), which
simply calls a virtual on an SkFieldVisitor for each field.
Currently, emitters and affectors use this mechanism.
- SkParticleSerialization.h demonstrates two useful field
visitors - for serializing to and from JSON. The driver
code that uses those is directly in ParticlesSlide.
- SkParticleData.h and SkCurve.h define a variety of helper
types for talking about particles, both for parameterizing
individual values, and communicating about the state of a
particle among the effect, affectors, and emitters.
- SkParticleEffect.h defines the static data definition of
an effect (SkParticleEffectParams), as well as a running
instance of an effect (SkParticleEffect). The effect has
simple update() and draw() methods.
- ParticlesSlide.cpp adds a third field visitor to generate
GUIs for interactively editing the running effect.
---
1: The critical change I'd like to make is to remove all
special case behavior over time and at spawn (setting sprite
frames, size over time, color over time, etc...). Integration
is the only fixed function behavior. Everything else is driven
by two lists of affectors. One is applied at spawn time, using
the effect's lifetime to evaluate curves. This allows spawning
particles with different colors as the effect ages out, for
example. The second list is applied every frame to update
existing particles, and is driven by the particle's lifetime.
This allows particles to change color after being spawned, for
example.
With a small set of affectors using a single expressive curve
primitive (keyframed list of cubic curve segments), we can
have affectors that update color, size, velocity, position,
sprite frame, etc., and implement many complex behaviors.
Bug: skia:
Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4
Reviewed-on: https://skia-review.googlesource.com/c/181404
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
|
|
|
|
2019-03-04 15:55:22 +00:00
|
|
|
SkScalar eval(const SkParticleUpdateParams& params, SkParticleState& ps) const;
|
Experimental Particle System
This adds a new "Particles" slide to viewer, that allows
editing, loading, and saving particle effects. All of the
particle system code is in modules/particles.
There are many rough edges and some not-yet-finished changes
to generalize the model[1]. A rough overview:
- SkReflected.h implements a lightweight reflection system
for classes derived from SkReflected. Adding a new class
involves deriving from SkReflected, adding a macro to the
class declaration, and implementing visitFields(), which
simply calls a virtual on an SkFieldVisitor for each field.
Currently, emitters and affectors use this mechanism.
- SkParticleSerialization.h demonstrates two useful field
visitors - for serializing to and from JSON. The driver
code that uses those is directly in ParticlesSlide.
- SkParticleData.h and SkCurve.h define a variety of helper
types for talking about particles, both for parameterizing
individual values, and communicating about the state of a
particle among the effect, affectors, and emitters.
- SkParticleEffect.h defines the static data definition of
an effect (SkParticleEffectParams), as well as a running
instance of an effect (SkParticleEffect). The effect has
simple update() and draw() methods.
- ParticlesSlide.cpp adds a third field visitor to generate
GUIs for interactively editing the running effect.
---
1: The critical change I'd like to make is to remove all
special case behavior over time and at spawn (setting sprite
frames, size over time, color over time, etc...). Integration
is the only fixed function behavior. Everything else is driven
by two lists of affectors. One is applied at spawn time, using
the effect's lifetime to evaluate curves. This allows spawning
particles with different colors as the effect ages out, for
example. The second list is applied every frame to update
existing particles, and is driven by the particle's lifetime.
This allows particles to change color after being spawned, for
example.
With a small set of affectors using a single expressive curve
primitive (keyframed list of cubic curve segments), we can
have affectors that update color, size, velocity, position,
sprite frame, etc., and implement many complex behaviors.
Bug: skia:
Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4
Reviewed-on: https://skia-review.googlesource.com/c/181404
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
|
|
|
void visitFields(SkFieldVisitor* v);
|
2019-02-19 20:39:18 +00:00
|
|
|
|
2019-03-04 15:55:22 +00:00
|
|
|
// Parameters that determine our x-value during evaluation
|
|
|
|
SkParticleValue fInput;
|
|
|
|
|
2019-02-19 20:39:18 +00:00
|
|
|
// It should always be true that (fXValues.count() + 1) == fSegments.count()
|
2019-02-14 21:55:21 +00:00
|
|
|
SkTArray<SkScalar, true> fXValues;
|
|
|
|
SkTArray<SkCurveSegment, true> fSegments;
|
Experimental Particle System
This adds a new "Particles" slide to viewer, that allows
editing, loading, and saving particle effects. All of the
particle system code is in modules/particles.
There are many rough edges and some not-yet-finished changes
to generalize the model[1]. A rough overview:
- SkReflected.h implements a lightweight reflection system
for classes derived from SkReflected. Adding a new class
involves deriving from SkReflected, adding a macro to the
class declaration, and implementing visitFields(), which
simply calls a virtual on an SkFieldVisitor for each field.
Currently, emitters and affectors use this mechanism.
- SkParticleSerialization.h demonstrates two useful field
visitors - for serializing to and from JSON. The driver
code that uses those is directly in ParticlesSlide.
- SkParticleData.h and SkCurve.h define a variety of helper
types for talking about particles, both for parameterizing
individual values, and communicating about the state of a
particle among the effect, affectors, and emitters.
- SkParticleEffect.h defines the static data definition of
an effect (SkParticleEffectParams), as well as a running
instance of an effect (SkParticleEffect). The effect has
simple update() and draw() methods.
- ParticlesSlide.cpp adds a third field visitor to generate
GUIs for interactively editing the running effect.
---
1: The critical change I'd like to make is to remove all
special case behavior over time and at spawn (setting sprite
frames, size over time, color over time, etc...). Integration
is the only fixed function behavior. Everything else is driven
by two lists of affectors. One is applied at spawn time, using
the effect's lifetime to evaluate curves. This allows spawning
particles with different colors as the effect ages out, for
example. The second list is applied every frame to update
existing particles, and is driven by the particle's lifetime.
This allows particles to change color after being spawned, for
example.
With a small set of affectors using a single expressive curve
primitive (keyframed list of cubic curve segments), we can
have affectors that update color, size, velocity, position,
sprite frame, etc., and implement many complex behaviors.
Bug: skia:
Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4
Reviewed-on: https://skia-review.googlesource.com/c/181404
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
|
|
|
};
|
|
|
|
|
2019-02-20 17:25:20 +00:00
|
|
|
/**
|
|
|
|
* SkColorCurve is similar to SkCurve, but keyframes 4D values - specifically colors. Because
|
|
|
|
* negative colors rarely make sense, SkColorCurves do not support bidirectional segments, but
|
|
|
|
* support all other features (including cubic interpolation).
|
|
|
|
*/
|
|
|
|
|
|
|
|
struct SkColorCurveSegment {
|
|
|
|
SkColorCurveSegment() {
|
|
|
|
for (int i = 0; i < 4; ++i) {
|
|
|
|
fMin[i] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
|
|
|
fMax[i] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-04 15:55:22 +00:00
|
|
|
SkColor4f eval(SkScalar x, SkScalar t) const;
|
2019-02-20 17:25:20 +00:00
|
|
|
void visitFields(SkFieldVisitor* v);
|
|
|
|
|
|
|
|
void setConstant(SkColor4f c) {
|
2019-02-27 16:19:19 +00:00
|
|
|
fType = kConstant_SegmentType;
|
2019-02-20 17:25:20 +00:00
|
|
|
fRanged = false;
|
|
|
|
fMin[0] = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
SkColor4f fMin[4];
|
|
|
|
SkColor4f fMax[4];
|
|
|
|
|
2019-02-27 16:19:19 +00:00
|
|
|
int fType = kConstant_SegmentType;
|
2019-02-20 17:25:20 +00:00
|
|
|
bool fRanged = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct SkColorCurve {
|
|
|
|
SkColorCurve(SkColor4f c = { 1.0f, 1.0f, 1.0f, 1.0f }) {
|
|
|
|
fSegments.push_back().setConstant(c);
|
|
|
|
}
|
|
|
|
|
2019-03-04 15:55:22 +00:00
|
|
|
SkColor4f eval(const SkParticleUpdateParams& params, SkParticleState& ps) const;
|
2019-02-20 17:25:20 +00:00
|
|
|
void visitFields(SkFieldVisitor* v);
|
|
|
|
|
2019-03-04 15:55:22 +00:00
|
|
|
SkParticleValue fInput;
|
2019-02-20 17:25:20 +00:00
|
|
|
SkTArray<SkScalar, true> fXValues;
|
|
|
|
SkTArray<SkColorCurveSegment, true> fSegments;
|
|
|
|
};
|
|
|
|
|
Experimental Particle System
This adds a new "Particles" slide to viewer, that allows
editing, loading, and saving particle effects. All of the
particle system code is in modules/particles.
There are many rough edges and some not-yet-finished changes
to generalize the model[1]. A rough overview:
- SkReflected.h implements a lightweight reflection system
for classes derived from SkReflected. Adding a new class
involves deriving from SkReflected, adding a macro to the
class declaration, and implementing visitFields(), which
simply calls a virtual on an SkFieldVisitor for each field.
Currently, emitters and affectors use this mechanism.
- SkParticleSerialization.h demonstrates two useful field
visitors - for serializing to and from JSON. The driver
code that uses those is directly in ParticlesSlide.
- SkParticleData.h and SkCurve.h define a variety of helper
types for talking about particles, both for parameterizing
individual values, and communicating about the state of a
particle among the effect, affectors, and emitters.
- SkParticleEffect.h defines the static data definition of
an effect (SkParticleEffectParams), as well as a running
instance of an effect (SkParticleEffect). The effect has
simple update() and draw() methods.
- ParticlesSlide.cpp adds a third field visitor to generate
GUIs for interactively editing the running effect.
---
1: The critical change I'd like to make is to remove all
special case behavior over time and at spawn (setting sprite
frames, size over time, color over time, etc...). Integration
is the only fixed function behavior. Everything else is driven
by two lists of affectors. One is applied at spawn time, using
the effect's lifetime to evaluate curves. This allows spawning
particles with different colors as the effect ages out, for
example. The second list is applied every frame to update
existing particles, and is driven by the particle's lifetime.
This allows particles to change color after being spawned, for
example.
With a small set of affectors using a single expressive curve
primitive (keyframed list of cubic curve segments), we can
have affectors that update color, size, velocity, position,
sprite frame, etc., and implement many complex behaviors.
Bug: skia:
Change-Id: Id9402bef22825d55d021c5a2f9e5e41791aabaf4
Reviewed-on: https://skia-review.googlesource.com/c/181404
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Mike Reed <reed@google.com>
2019-02-12 18:27:51 +00:00
|
|
|
#endif // SkCurve_DEFINED
|