blob: de1a66c2d8d55123ce9c035af105a13b1b3764ae [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
Brian Osman8b6283f2019-02-14 16:55:21 -050010#include "SkCurve.h"
Brian Osman7c979f52019-02-12 13:27:51 -050011#include "SkParticleData.h"
12#include "SkRandom.h"
13
Brian Osman14a67a32019-02-25 14:30:44 -050014void SkParticleAffector::apply(SkParticleUpdateParams& params, SkParticleState ps[], int count) {
Brian Osman1b20cd82019-02-25 14:15:02 -050015 if (fEnabled) {
Brian Osman14a67a32019-02-25 14:30:44 -050016 this->onApply(params, ps, count);
Brian Osman1b20cd82019-02-25 14:15:02 -050017 }
18}
19
20void SkParticleAffector::visitFields(SkFieldVisitor* v) {
21 v->visit("Enabled", fEnabled);
22}
23
Brian Osman8b6283f2019-02-14 16:55:21 -050024class SkLinearVelocityAffector : public SkParticleAffector {
Brian Osman7c979f52019-02-12 13:27:51 -050025public:
Brian Osman8b6283f2019-02-14 16:55:21 -050026 SkLinearVelocityAffector(const SkCurve& angle = 0.0f,
27 const SkCurve& strength = 0.0f,
Brian Osmand5c57fe2019-02-22 11:48:18 -050028 bool force = true,
29 bool local = false)
Brian Osman8b6283f2019-02-14 16:55:21 -050030 : fAngle(angle)
31 , fStrength(strength)
Brian Osmand5c57fe2019-02-22 11:48:18 -050032 , fForce(force)
33 , fLocal(local) {}
Brian Osman7c979f52019-02-12 13:27:51 -050034
Brian Osman8b6283f2019-02-14 16:55:21 -050035 REFLECTED(SkLinearVelocityAffector, SkParticleAffector)
Brian Osman7c979f52019-02-12 13:27:51 -050036
Brian Osman14a67a32019-02-25 14:30:44 -050037 void onApply(SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
38 for (int i = 0; i < count; ++i) {
39 float angle = fAngle.eval(ps[i].fAge, ps[i].fStableRandom);
40 SkScalar c_local, s_local = SkScalarSinCos(SkDegreesToRadians(angle), &c_local);
41 SkVector heading = fLocal ? ps[i].fPose.fHeading : SkVector{ 0, -1 };
42 SkScalar c = heading.fX * c_local - heading.fY * s_local;
43 SkScalar s = heading.fX * s_local + heading.fY * c_local;
44 float strength = fStrength.eval(ps[i].fAge, ps[i].fStableRandom);
45 SkVector force = { c * strength, s * strength };
46 if (fForce) {
47 ps[i].fVelocity.fLinear += force * params.fDeltaTime;
48 } else {
49 ps[i].fVelocity.fLinear = force;
50 }
Brian Osman8b6283f2019-02-14 16:55:21 -050051 }
Brian Osman7c979f52019-02-12 13:27:51 -050052 }
53
54 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -050055 SkParticleAffector::visitFields(v);
Brian Osman7c979f52019-02-12 13:27:51 -050056 v->visit("Force", fForce);
Brian Osmand5c57fe2019-02-22 11:48:18 -050057 v->visit("Local", fLocal);
Brian Osman7c979f52019-02-12 13:27:51 -050058 v->visit("Angle", fAngle);
59 v->visit("Strength", fStrength);
Brian Osman7c979f52019-02-12 13:27:51 -050060 }
61
62private:
63 SkCurve fAngle;
64 SkCurve fStrength;
Brian Osman8b6283f2019-02-14 16:55:21 -050065 bool fForce;
Brian Osmand5c57fe2019-02-22 11:48:18 -050066 bool fLocal;
Brian Osman7c979f52019-02-12 13:27:51 -050067};
68
69class SkPointForceAffector : public SkParticleAffector {
70public:
71 SkPointForceAffector(SkPoint point = { 0.0f, 0.0f }, SkScalar constant = 0.0f,
72 SkScalar invSquare = 0.0f)
73 : fPoint(point), fConstant(constant), fInvSquare(invSquare) {}
74
75 REFLECTED(SkPointForceAffector, SkParticleAffector)
76
Brian Osman14a67a32019-02-25 14:30:44 -050077 void onApply(SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
78 for (int i = 0; i < count; ++i) {
79 SkVector toPoint = fPoint - ps[i].fPose.fPosition;
80 SkScalar lenSquare = toPoint.dot(toPoint);
81 toPoint.normalize();
82 ps[i].fVelocity.fLinear +=
83 toPoint * (fConstant + (fInvSquare / lenSquare)) * params.fDeltaTime;
84 }
Brian Osman7c979f52019-02-12 13:27:51 -050085 }
86
87 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -050088 SkParticleAffector::visitFields(v);
Brian Osman7c979f52019-02-12 13:27:51 -050089 v->visit("Point", fPoint);
90 v->visit("Constant", fConstant);
91 v->visit("InvSquare", fInvSquare);
92 }
93
94private:
95 SkPoint fPoint;
96 SkScalar fConstant;
97 SkScalar fInvSquare;
98};
99
100class SkOrientAlongVelocityAffector : public SkParticleAffector {
101public:
102 SkOrientAlongVelocityAffector() {}
103
104 REFLECTED(SkOrientAlongVelocityAffector, SkParticleAffector)
105
Brian Osman14a67a32019-02-25 14:30:44 -0500106 void onApply(SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
107 for (int i = 0; i < count; ++i) {
108 SkVector heading = ps[i].fVelocity.fLinear;
109 if (!heading.normalize()) {
110 heading.set(0, -1);
111 }
112 ps[i].fPose.fHeading = heading;
Brian Osman7c979f52019-02-12 13:27:51 -0500113 }
Brian Osman7c979f52019-02-12 13:27:51 -0500114 }
115
Brian Osman1b20cd82019-02-25 14:15:02 -0500116 void visitFields(SkFieldVisitor *v) override {
117 SkParticleAffector::visitFields(v);
118 }
Brian Osman7c979f52019-02-12 13:27:51 -0500119};
120
Brian Osman8b6283f2019-02-14 16:55:21 -0500121class SkSizeAffector : public SkParticleAffector {
Brian Osman7c979f52019-02-12 13:27:51 -0500122public:
Brian Osman8b6283f2019-02-14 16:55:21 -0500123 SkSizeAffector(const SkCurve& curve = 1.0f) : fCurve(curve) {}
Brian Osman7c979f52019-02-12 13:27:51 -0500124
Brian Osman8b6283f2019-02-14 16:55:21 -0500125 REFLECTED(SkSizeAffector, SkParticleAffector)
Brian Osman7c979f52019-02-12 13:27:51 -0500126
Brian Osman14a67a32019-02-25 14:30:44 -0500127 void onApply(SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
128 for (int i = 0; i < count; ++i) {
129 ps[i].fPose.fScale = fCurve.eval(ps[i].fAge, ps[i].fStableRandom);
130 }
Brian Osman7c979f52019-02-12 13:27:51 -0500131 }
132
133 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -0500134 SkParticleAffector::visitFields(v);
Brian Osman8b6283f2019-02-14 16:55:21 -0500135 v->visit("Curve", fCurve);
Brian Osman7c979f52019-02-12 13:27:51 -0500136 }
137
138private:
Brian Osman8b6283f2019-02-14 16:55:21 -0500139 SkCurve fCurve;
Brian Osman7c979f52019-02-12 13:27:51 -0500140};
141
Brian Osman125daa42019-02-20 12:25:20 -0500142class SkFrameAffector : public SkParticleAffector {
143public:
144 SkFrameAffector(const SkCurve& curve = 1.0f) : fCurve(curve) {}
145
146 REFLECTED(SkFrameAffector, SkParticleAffector)
147
Brian Osman14a67a32019-02-25 14:30:44 -0500148 void onApply(SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
149 for (int i = 0; i < count; ++i) {
150 ps[i].fFrame = fCurve.eval(ps[i].fAge, ps[i].fStableRandom);
151 }
Brian Osman125daa42019-02-20 12:25:20 -0500152 }
153
154 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -0500155 SkParticleAffector::visitFields(v);
Brian Osman125daa42019-02-20 12:25:20 -0500156 v->visit("Curve", fCurve);
157 }
158
159private:
160 SkCurve fCurve;
161};
162
163class SkColorAffector : public SkParticleAffector {
164public:
165 SkColorAffector(const SkColorCurve& curve = SkColor4f{ 1.0f, 1.0f, 1.0f, 1.0f })
166 : fCurve(curve) {}
167
168 REFLECTED(SkColorAffector, SkParticleAffector)
169
Brian Osman14a67a32019-02-25 14:30:44 -0500170 void onApply(SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
171 for (int i = 0; i < count; ++i) {
172 ps[i].fColor = fCurve.eval(ps[i].fAge, ps[i].fStableRandom);
173 }
Brian Osman125daa42019-02-20 12:25:20 -0500174 }
175
176 void visitFields(SkFieldVisitor* v) override {
Brian Osman1b20cd82019-02-25 14:15:02 -0500177 SkParticleAffector::visitFields(v);
Brian Osman125daa42019-02-20 12:25:20 -0500178 v->visit("Curve", fCurve);
179 }
180
181private:
182 SkColorCurve fCurve;
183};
184
Brian Osman7c979f52019-02-12 13:27:51 -0500185void SkParticleAffector::RegisterAffectorTypes() {
186 REGISTER_REFLECTED(SkParticleAffector);
Brian Osman8b6283f2019-02-14 16:55:21 -0500187 REGISTER_REFLECTED(SkLinearVelocityAffector);
Brian Osman7c979f52019-02-12 13:27:51 -0500188 REGISTER_REFLECTED(SkPointForceAffector);
189 REGISTER_REFLECTED(SkOrientAlongVelocityAffector);
Brian Osman8b6283f2019-02-14 16:55:21 -0500190 REGISTER_REFLECTED(SkSizeAffector);
Brian Osman125daa42019-02-20 12:25:20 -0500191 REGISTER_REFLECTED(SkFrameAffector);
192 REGISTER_REFLECTED(SkColorAffector);
Brian Osman7c979f52019-02-12 13:27:51 -0500193}
194
Brian Osman8b6283f2019-02-14 16:55:21 -0500195sk_sp<SkParticleAffector> SkParticleAffector::MakeLinearVelocity(const SkCurve& angle,
196 const SkCurve& strength,
Brian Osmand5c57fe2019-02-22 11:48:18 -0500197 bool force,
198 bool local) {
199 return sk_sp<SkParticleAffector>(new SkLinearVelocityAffector(angle, strength, force, local));
Brian Osman7c979f52019-02-12 13:27:51 -0500200}
201
Brian Osman8b6283f2019-02-14 16:55:21 -0500202sk_sp<SkParticleAffector> SkParticleAffector::MakePointForce(SkPoint point, SkScalar constant,
203 SkScalar invSquare) {
Brian Osman7c979f52019-02-12 13:27:51 -0500204 return sk_sp<SkParticleAffector>(new SkPointForceAffector(point, constant, invSquare));
205}
206
Brian Osman8b6283f2019-02-14 16:55:21 -0500207sk_sp<SkParticleAffector> SkParticleAffector::MakeOrientAlongVelocity() {
Brian Osman7c979f52019-02-12 13:27:51 -0500208 return sk_sp<SkParticleAffector>(new SkOrientAlongVelocityAffector());
209}
Brian Osman8b6283f2019-02-14 16:55:21 -0500210
Brian Osman125daa42019-02-20 12:25:20 -0500211sk_sp<SkParticleAffector> SkParticleAffector::MakeSize(const SkCurve& curve) {
Brian Osman8b6283f2019-02-14 16:55:21 -0500212 return sk_sp<SkParticleAffector>(new SkSizeAffector(curve));
213}
Brian Osman125daa42019-02-20 12:25:20 -0500214
215sk_sp<SkParticleAffector> SkParticleAffector::MakeFrame(const SkCurve& curve) {
216 return sk_sp<SkParticleAffector>(new SkFrameAffector(curve));
217}
218
219sk_sp<SkParticleAffector> SkParticleAffector::MakeColor(const SkColorCurve& curve) {
220 return sk_sp<SkParticleAffector>(new SkColorAffector(curve));
221}