blob: a22cd446a3e5fa1e452ea191b3896d6d29ccd82e [file] [log] [blame]
Brian Osman7c979f52019-02-12 13:27:51 -05001/*
2* Copyright 2019 Google LLC
3*
4* Use of this source code is governed by a BSD-style license that can be
5* found in the LICENSE file.
6*/
7
8#include "SkParticleAffector.h"
9
10#include "SkParticleData.h"
11#include "SkRandom.h"
12
13class SkDirectionalForceAffector : public SkParticleAffector {
14public:
15 SkDirectionalForceAffector(SkVector force = { 0.0f, 0.0f }) : fForce(force) {}
16
17 REFLECTED(SkDirectionalForceAffector, SkParticleAffector)
18
19 void apply(SkParticleUpdateParams& params, SkParticlePoseAndVelocity& pv) override {
20 pv.fVelocity.fLinear += fForce * params.fDeltaTime;
21 }
22
23 void visitFields(SkFieldVisitor* v) override {
24 v->visit("Force", fForce);
25 }
26
27private:
28 SkVector fForce;
29};
30
31class SkRangedForceAffector : public SkParticleAffector {
32public:
33 SkRangedForceAffector(const SkCurve& angle = 0.0f,
34 const SkCurve& strength = 0.0f,
35 bool bidirectional = false)
36 : fAngle(angle)
37 , fStrength(strength)
38 , fBidirectional(bidirectional) {}
39
40 REFLECTED(SkRangedForceAffector, SkParticleAffector)
41
42 void apply(SkParticleUpdateParams& params, SkParticlePoseAndVelocity& pv) override {
43 float angle = fAngle.eval(params.fParticleT, *params.fStableRandom);
44 SkScalar c, s = SkScalarSinCos(angle, &c);
45 float strength = fStrength.eval(params.fParticleT, *params.fStableRandom);
46 if (fBidirectional && params.fStableRandom->nextBool()) {
47 strength = -strength;
48 }
49 SkVector force = { c * strength, s * strength };
50 pv.fVelocity.fLinear += force * params.fDeltaTime;
51 }
52
53 void visitFields(SkFieldVisitor* v) override {
54 v->visit("Angle", fAngle);
55 v->visit("Strength", fStrength);
56 v->visit("Bidirectional", fBidirectional);
57 }
58
59private:
60 SkCurve fAngle;
61 SkCurve fStrength;
62 bool fBidirectional;
63};
64
65class SkPointForceAffector : public SkParticleAffector {
66public:
67 SkPointForceAffector(SkPoint point = { 0.0f, 0.0f }, SkScalar constant = 0.0f,
68 SkScalar invSquare = 0.0f)
69 : fPoint(point), fConstant(constant), fInvSquare(invSquare) {}
70
71 REFLECTED(SkPointForceAffector, SkParticleAffector)
72
73 void apply(SkParticleUpdateParams& params, SkParticlePoseAndVelocity& pv) override {
74 SkVector toPoint = fPoint - pv.fPose.fPosition;
75 SkScalar lenSquare = toPoint.dot(toPoint);
76 toPoint.normalize();
77 pv.fVelocity.fLinear += toPoint * (fConstant + (fInvSquare/lenSquare)) * params.fDeltaTime;
78 }
79
80 void visitFields(SkFieldVisitor* v) override {
81 v->visit("Point", fPoint);
82 v->visit("Constant", fConstant);
83 v->visit("InvSquare", fInvSquare);
84 }
85
86private:
87 SkPoint fPoint;
88 SkScalar fConstant;
89 SkScalar fInvSquare;
90};
91
92class SkOrientAlongVelocityAffector : public SkParticleAffector {
93public:
94 SkOrientAlongVelocityAffector() {}
95
96 REFLECTED(SkOrientAlongVelocityAffector, SkParticleAffector)
97
98 void apply(SkParticleUpdateParams& params, SkParticlePoseAndVelocity& pv) override {
99 SkVector heading = pv.fVelocity.fLinear;
100 if (!heading.normalize()) {
101 heading.set(0, -1);
102 }
103 pv.fPose.fHeading = heading;
104 }
105
106 void visitFields(SkFieldVisitor*) override {}
107};
108
109class SkJitterAffector : public SkParticleAffector {
110public:
111 SkJitterAffector() {}
112
113 REFLECTED(SkJitterAffector, SkParticleAffector)
114
115 void apply(SkParticleUpdateParams& params, SkParticlePoseAndVelocity& pv) override {
116 pv.fVelocity.fLinear.fX += fX.eval(*params.fRandom);
117 }
118
119 void visitFields(SkFieldVisitor* v) override {
120 v->visit("X", fX);
121 }
122
123private:
124 SkRangedFloat fX;
125};
126
127void SkParticleAffector::RegisterAffectorTypes() {
128 REGISTER_REFLECTED(SkParticleAffector);
129 REGISTER_REFLECTED(SkDirectionalForceAffector);
130 REGISTER_REFLECTED(SkRangedForceAffector);
131 REGISTER_REFLECTED(SkPointForceAffector);
132 REGISTER_REFLECTED(SkOrientAlongVelocityAffector);
133 REGISTER_REFLECTED(SkJitterAffector);
134}
135
136sk_sp<SkParticleAffector> SkParticleAffector::MakeDirectionalForce(SkVector force) {
137 return sk_sp<SkParticleAffector>(new SkDirectionalForceAffector(force));
138}
139
140sk_sp<SkParticleAffector> SkParticleAffector::MakeRangedForce(const SkCurve& angle,
141 const SkCurve& strength,
142 bool bidirectional) {
143 return sk_sp<SkParticleAffector>(new SkRangedForceAffector(angle, strength, bidirectional));
144}
145
146sk_sp<SkParticleAffector> MakePointForce(SkPoint point, SkScalar constant, SkScalar invSquare) {
147 return sk_sp<SkParticleAffector>(new SkPointForceAffector(point, constant, invSquare));
148}
149
150sk_sp<SkParticleAffector> MakeOrientAlongVelocity() {
151 return sk_sp<SkParticleAffector>(new SkOrientAlongVelocityAffector());
152}