Few more particle features and some generalization work
Add particle "frame" enum, to allow effects relative to local, world, or velocity. Remove the "orient along velocity" and replace with a much more general orientation affector (angle curve + frame). Add an angular velocity affector to mirror the behavior of the linear velocity affector. Bug: skia: Change-Id: Ibbaaeb352c9547d00d81c7916d00148dd65ed2b9 Reviewed-on: https://skia-review.googlesource.com/c/195361 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
804f17e35b
commit
0c48681e58
@ -17,6 +17,12 @@ struct SkCurve;
|
||||
struct SkParticleState;
|
||||
struct SkParticleUpdateParams;
|
||||
|
||||
enum SkParticleFrame {
|
||||
kWorld_ParticleFrame, // "Up" is { 0, -1 }
|
||||
kLocal_ParticleFrame, // "Up" is particle's heading
|
||||
kVelocity_ParticleFrame, // "Up" is particle's direction of travel
|
||||
};
|
||||
|
||||
class SkParticleAffector : public SkReflected {
|
||||
public:
|
||||
REFLECTED_ABSTRACT(SkParticleAffector, SkReflected)
|
||||
@ -26,13 +32,21 @@ public:
|
||||
|
||||
static void RegisterAffectorTypes();
|
||||
|
||||
// Affectors that can set the linear or angular velocity. Both have a 'force' option to apply
|
||||
// the resulting value as a force, rather than directly setting the velocity.
|
||||
static sk_sp<SkParticleAffector> MakeLinearVelocity(const SkCurve& angle,
|
||||
const SkCurve& strength,
|
||||
bool force,
|
||||
bool local);
|
||||
SkParticleFrame frame);
|
||||
static sk_sp<SkParticleAffector> MakeAngularVelocity(const SkCurve& strength,
|
||||
bool force);
|
||||
|
||||
// Set the orientation of a particle, relative to the world, local, or velocity frame.
|
||||
static sk_sp<SkParticleAffector> MakeOrientation(const SkCurve& angle,
|
||||
SkParticleFrame frame);
|
||||
|
||||
static sk_sp<SkParticleAffector> MakePointForce(SkPoint point, SkScalar constant,
|
||||
SkScalar invSquare);
|
||||
static sk_sp<SkParticleAffector> MakeOrientAlongVelocity();
|
||||
|
||||
static sk_sp<SkParticleAffector> MakeSize(const SkCurve& curve);
|
||||
static sk_sp<SkParticleAffector> MakeFrame(const SkCurve& curve);
|
||||
|
@ -21,16 +21,33 @@ void SkParticleAffector::visitFields(SkFieldVisitor* v) {
|
||||
v->visit("Enabled", fEnabled);
|
||||
}
|
||||
|
||||
static inline SkVector get_heading(const SkParticleState& ps, SkParticleFrame frame) {
|
||||
switch (frame) {
|
||||
case kLocal_ParticleFrame:
|
||||
return ps.fPose.fHeading;
|
||||
case kVelocity_ParticleFrame: {
|
||||
SkVector heading = ps.fVelocity.fLinear;
|
||||
if (!heading.normalize()) {
|
||||
heading.set(0, -1);
|
||||
}
|
||||
return heading;
|
||||
}
|
||||
case kWorld_ParticleFrame:
|
||||
default:
|
||||
return SkVector{ 0, -1 };
|
||||
}
|
||||
}
|
||||
|
||||
class SkLinearVelocityAffector : public SkParticleAffector {
|
||||
public:
|
||||
SkLinearVelocityAffector(const SkCurve& angle = 0.0f,
|
||||
const SkCurve& strength = 0.0f,
|
||||
bool force = true,
|
||||
bool local = false)
|
||||
SkParticleFrame frame = kWorld_ParticleFrame)
|
||||
: fAngle(angle)
|
||||
, fStrength(strength)
|
||||
, fForce(force)
|
||||
, fLocal(local) {}
|
||||
, fFrame(frame) {}
|
||||
|
||||
REFLECTED(SkLinearVelocityAffector, SkParticleAffector)
|
||||
|
||||
@ -38,7 +55,7 @@ public:
|
||||
for (int i = 0; i < count; ++i) {
|
||||
float angle = fAngle.eval(ps[i].fAge, ps[i].fStableRandom);
|
||||
SkScalar c_local, s_local = SkScalarSinCos(SkDegreesToRadians(angle), &c_local);
|
||||
SkVector heading = fLocal ? ps[i].fPose.fHeading : SkVector{ 0, -1 };
|
||||
SkVector heading = get_heading(ps[i], static_cast<SkParticleFrame>(fFrame));
|
||||
SkScalar c = heading.fX * c_local - heading.fY * s_local;
|
||||
SkScalar s = heading.fX * s_local + heading.fY * c_local;
|
||||
float strength = fStrength.eval(ps[i].fAge, ps[i].fStableRandom);
|
||||
@ -54,7 +71,7 @@ public:
|
||||
void visitFields(SkFieldVisitor* v) override {
|
||||
SkParticleAffector::visitFields(v);
|
||||
v->visit("Force", fForce);
|
||||
v->visit("Local", fLocal);
|
||||
v->visit("Frame", fFrame);
|
||||
v->visit("Angle", fAngle);
|
||||
v->visit("Strength", fStrength);
|
||||
}
|
||||
@ -63,7 +80,37 @@ private:
|
||||
SkCurve fAngle;
|
||||
SkCurve fStrength;
|
||||
bool fForce;
|
||||
bool fLocal;
|
||||
int fFrame;
|
||||
};
|
||||
|
||||
class SkAngularVelocityAffector : public SkParticleAffector {
|
||||
public:
|
||||
SkAngularVelocityAffector(const SkCurve& strength = 0.0f, bool force = true)
|
||||
: fStrength(strength)
|
||||
, fForce(force) {}
|
||||
|
||||
REFLECTED(SkAngularVelocityAffector, SkParticleAffector)
|
||||
|
||||
void onApply(SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
float strength = fStrength.eval(ps[i].fAge, ps[i].fStableRandom);
|
||||
if (fForce) {
|
||||
ps[i].fVelocity.fAngular += strength * params.fDeltaTime;
|
||||
} else {
|
||||
ps[i].fVelocity.fAngular = strength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void visitFields(SkFieldVisitor* v) override {
|
||||
SkParticleAffector::visitFields(v);
|
||||
v->visit("Force", fForce);
|
||||
v->visit("Strength", fStrength);
|
||||
}
|
||||
|
||||
private:
|
||||
SkCurve fStrength;
|
||||
bool fForce;
|
||||
};
|
||||
|
||||
class SkPointForceAffector : public SkParticleAffector {
|
||||
@ -97,25 +144,34 @@ private:
|
||||
SkScalar fInvSquare;
|
||||
};
|
||||
|
||||
class SkOrientAlongVelocityAffector : public SkParticleAffector {
|
||||
class SkOrientationAffector : public SkParticleAffector {
|
||||
public:
|
||||
SkOrientAlongVelocityAffector() {}
|
||||
SkOrientationAffector(const SkCurve& angle = 0.0f,
|
||||
SkParticleFrame frame = kLocal_ParticleFrame)
|
||||
: fAngle(angle)
|
||||
, fFrame(frame) {}
|
||||
|
||||
REFLECTED(SkOrientAlongVelocityAffector, SkParticleAffector)
|
||||
REFLECTED(SkOrientationAffector, SkParticleAffector)
|
||||
|
||||
void onApply(SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
SkVector heading = ps[i].fVelocity.fLinear;
|
||||
if (!heading.normalize()) {
|
||||
heading.set(0, -1);
|
||||
}
|
||||
ps[i].fPose.fHeading = heading;
|
||||
float angle = fAngle.eval(ps[i].fAge, ps[i].fStableRandom);
|
||||
SkScalar c_local, s_local = SkScalarSinCos(SkDegreesToRadians(angle), &c_local);
|
||||
SkVector heading = get_heading(ps[i], static_cast<SkParticleFrame>(fFrame));
|
||||
ps[i].fPose.fHeading.set(heading.fX * c_local - heading.fY * s_local,
|
||||
heading.fX * s_local + heading.fY * c_local);
|
||||
}
|
||||
}
|
||||
|
||||
void visitFields(SkFieldVisitor *v) override {
|
||||
SkParticleAffector::visitFields(v);
|
||||
v->visit("Frame", fFrame);
|
||||
v->visit("Angle", fAngle);
|
||||
}
|
||||
|
||||
private:
|
||||
SkCurve fAngle;
|
||||
int fFrame;
|
||||
};
|
||||
|
||||
class SkSizeAffector : public SkParticleAffector {
|
||||
@ -185,8 +241,9 @@ private:
|
||||
void SkParticleAffector::RegisterAffectorTypes() {
|
||||
REGISTER_REFLECTED(SkParticleAffector);
|
||||
REGISTER_REFLECTED(SkLinearVelocityAffector);
|
||||
REGISTER_REFLECTED(SkAngularVelocityAffector);
|
||||
REGISTER_REFLECTED(SkPointForceAffector);
|
||||
REGISTER_REFLECTED(SkOrientAlongVelocityAffector);
|
||||
REGISTER_REFLECTED(SkOrientationAffector);
|
||||
REGISTER_REFLECTED(SkSizeAffector);
|
||||
REGISTER_REFLECTED(SkFrameAffector);
|
||||
REGISTER_REFLECTED(SkColorAffector);
|
||||
@ -195,8 +252,13 @@ void SkParticleAffector::RegisterAffectorTypes() {
|
||||
sk_sp<SkParticleAffector> SkParticleAffector::MakeLinearVelocity(const SkCurve& angle,
|
||||
const SkCurve& strength,
|
||||
bool force,
|
||||
bool local) {
|
||||
return sk_sp<SkParticleAffector>(new SkLinearVelocityAffector(angle, strength, force, local));
|
||||
SkParticleFrame frame) {
|
||||
return sk_sp<SkParticleAffector>(new SkLinearVelocityAffector(angle, strength, force, frame));
|
||||
}
|
||||
|
||||
sk_sp<SkParticleAffector> SkParticleAffector::MakeAngularVelocity(const SkCurve& strength,
|
||||
bool force) {
|
||||
return sk_sp<SkParticleAffector>(new SkAngularVelocityAffector(strength, force));
|
||||
}
|
||||
|
||||
sk_sp<SkParticleAffector> SkParticleAffector::MakePointForce(SkPoint point, SkScalar constant,
|
||||
@ -204,8 +266,9 @@ sk_sp<SkParticleAffector> SkParticleAffector::MakePointForce(SkPoint point, SkSc
|
||||
return sk_sp<SkParticleAffector>(new SkPointForceAffector(point, constant, invSquare));
|
||||
}
|
||||
|
||||
sk_sp<SkParticleAffector> SkParticleAffector::MakeOrientAlongVelocity() {
|
||||
return sk_sp<SkParticleAffector>(new SkOrientAlongVelocityAffector());
|
||||
sk_sp<SkParticleAffector> SkParticleAffector::MakeOrientation(const SkCurve& angle,
|
||||
SkParticleFrame frame) {
|
||||
return sk_sp<SkParticleAffector>(new SkOrientationAffector(angle, frame));
|
||||
}
|
||||
|
||||
sk_sp<SkParticleAffector> SkParticleAffector::MakeSize(const SkCurve& curve) {
|
||||
|
@ -32,8 +32,9 @@
|
||||
"Spawn": [
|
||||
{
|
||||
"Type": "SkLinearVelocityAffector",
|
||||
"Enabled": true,
|
||||
"Force": false,
|
||||
"Local": false,
|
||||
"Frame": 0,
|
||||
"Angle": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
@ -75,6 +76,7 @@
|
||||
"Update": [
|
||||
{
|
||||
"Type": "SkColorAffector",
|
||||
"Enabled": true,
|
||||
"Curve": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
|
@ -35,12 +35,14 @@
|
||||
"Update": [
|
||||
{
|
||||
"Type": "SkPointForceAffector",
|
||||
"Enabled": true,
|
||||
"Point": { "x": 200, "y": 200 },
|
||||
"Constant": 0,
|
||||
"InvSquare": -50
|
||||
},
|
||||
{
|
||||
"Type": "SkFrameAffector",
|
||||
"Enabled": true,
|
||||
"Curve": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
|
@ -34,8 +34,9 @@
|
||||
"Spawn": [
|
||||
{
|
||||
"Type": "SkLinearVelocityAffector",
|
||||
"Enabled": true,
|
||||
"Force": false,
|
||||
"Local": false,
|
||||
"Frame": 0,
|
||||
"Angle": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
@ -77,8 +78,9 @@
|
||||
"Update": [
|
||||
{
|
||||
"Type": "SkLinearVelocityAffector",
|
||||
"Enabled": true,
|
||||
"Force": true,
|
||||
"Local": false,
|
||||
"Frame": 0,
|
||||
"Angle": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
@ -117,7 +119,27 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"Type": "SkOrientAlongVelocityAffector"
|
||||
"Type": "SkOrientationAffector",
|
||||
"Enabled": true,
|
||||
"Frame": 2,
|
||||
"Angle": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
{
|
||||
"Constant": true,
|
||||
"Ranged": false,
|
||||
"Bidirectional": false,
|
||||
"A0": 0,
|
||||
"B0": 0,
|
||||
"C0": 0,
|
||||
"D0": 0,
|
||||
"A1": 0,
|
||||
"B1": 0,
|
||||
"C1": 0,
|
||||
"D1": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -32,8 +32,9 @@
|
||||
"Spawn": [
|
||||
{
|
||||
"Type": "SkLinearVelocityAffector",
|
||||
"Enabled": true,
|
||||
"Force": false,
|
||||
"Local": false,
|
||||
"Frame": 0,
|
||||
"Angle": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
@ -75,6 +76,7 @@
|
||||
"Update": [
|
||||
{
|
||||
"Type": "SkSizeAffector",
|
||||
"Enabled": true,
|
||||
"Curve": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
|
@ -32,7 +32,9 @@
|
||||
"Spawn": [
|
||||
{
|
||||
"Type": "SkLinearVelocityAffector",
|
||||
"Enabled": true,
|
||||
"Force": false,
|
||||
"Frame": 0,
|
||||
"Angle": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
@ -74,6 +76,7 @@
|
||||
"Update": [
|
||||
{
|
||||
"Type": "SkSizeAffector",
|
||||
"Enabled": true,
|
||||
"Curve": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
@ -95,6 +98,7 @@
|
||||
},
|
||||
{
|
||||
"Type": "SkColorAffector",
|
||||
"Enabled": true,
|
||||
"Curve": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
|
@ -32,8 +32,9 @@
|
||||
"Spawn": [
|
||||
{
|
||||
"Type": "SkLinearVelocityAffector",
|
||||
"Enabled": true,
|
||||
"Force": false,
|
||||
"Local": false,
|
||||
"Frame": 0,
|
||||
"Angle": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
@ -75,8 +76,9 @@
|
||||
"Update": [
|
||||
{
|
||||
"Type": "SkLinearVelocityAffector",
|
||||
"Enabled": true,
|
||||
"Force": true,
|
||||
"Local": false,
|
||||
"Frame": 0,
|
||||
"Angle": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
@ -116,6 +118,7 @@
|
||||
},
|
||||
{
|
||||
"Type": "SkSizeAffector",
|
||||
"Enabled": true,
|
||||
"Curve": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
@ -137,6 +140,7 @@
|
||||
},
|
||||
{
|
||||
"Type": "SkColorAffector",
|
||||
"Enabled": true,
|
||||
"Curve": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
|
@ -33,12 +33,14 @@
|
||||
"Update": [
|
||||
{
|
||||
"Type": "SkPointForceAffector",
|
||||
"Enabled": true,
|
||||
"Point": { "x": 375, "y": 273 },
|
||||
"Constant": -10,
|
||||
"InvSquare": 0
|
||||
},
|
||||
{
|
||||
"Type": "SkSizeAffector",
|
||||
"Enabled": true,
|
||||
"Curve": {
|
||||
"XValues": [],
|
||||
"Segments": [
|
||||
|
Loading…
Reference in New Issue
Block a user