blob: 24a84d175fa9d3e39f015d8b6bfce00e124ac785 [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 Osman8b6283f2019-02-14 16:55:21 -050014class SkLinearVelocityAffector : public SkParticleAffector {
Brian Osman7c979f52019-02-12 13:27:51 -050015public:
Brian Osman8b6283f2019-02-14 16:55:21 -050016 SkLinearVelocityAffector(const SkCurve& angle = 0.0f,
17 const SkCurve& strength = 0.0f,
18 bool force = true)
19 : fAngle(angle)
20 , fStrength(strength)
21 , fForce(force) {}
Brian Osman7c979f52019-02-12 13:27:51 -050022
Brian Osman8b6283f2019-02-14 16:55:21 -050023 REFLECTED(SkLinearVelocityAffector, SkParticleAffector)
Brian Osman7c979f52019-02-12 13:27:51 -050024
25 void apply(SkParticleUpdateParams& params, SkParticlePoseAndVelocity& pv) override {
Brian Osman8b6283f2019-02-14 16:55:21 -050026 float angle = fAngle.eval(params.fParticleT, *params.fStableRandom);
27 SkScalar c, s = SkScalarSinCos(SkDegreesToRadians(angle), &c);
28 float strength = fStrength.eval(params.fParticleT, *params.fStableRandom);
29 SkVector force = { c * strength, s * strength };
30 if (fForce) {
31 pv.fVelocity.fLinear += force * params.fDeltaTime;
32 } else {
33 pv.fVelocity.fLinear = force;
34 }
Brian Osman7c979f52019-02-12 13:27:51 -050035 }
36
37 void visitFields(SkFieldVisitor* v) override {
38 v->visit("Force", fForce);
Brian Osman7c979f52019-02-12 13:27:51 -050039 v->visit("Angle", fAngle);
40 v->visit("Strength", fStrength);
Brian Osman7c979f52019-02-12 13:27:51 -050041 }
42
43private:
44 SkCurve fAngle;
45 SkCurve fStrength;
Brian Osman8b6283f2019-02-14 16:55:21 -050046 bool fForce;
Brian Osman7c979f52019-02-12 13:27:51 -050047};
48
49class SkPointForceAffector : public SkParticleAffector {
50public:
51 SkPointForceAffector(SkPoint point = { 0.0f, 0.0f }, SkScalar constant = 0.0f,
52 SkScalar invSquare = 0.0f)
53 : fPoint(point), fConstant(constant), fInvSquare(invSquare) {}
54
55 REFLECTED(SkPointForceAffector, SkParticleAffector)
56
57 void apply(SkParticleUpdateParams& params, SkParticlePoseAndVelocity& pv) override {
58 SkVector toPoint = fPoint - pv.fPose.fPosition;
59 SkScalar lenSquare = toPoint.dot(toPoint);
60 toPoint.normalize();
61 pv.fVelocity.fLinear += toPoint * (fConstant + (fInvSquare/lenSquare)) * params.fDeltaTime;
62 }
63
64 void visitFields(SkFieldVisitor* v) override {
65 v->visit("Point", fPoint);
66 v->visit("Constant", fConstant);
67 v->visit("InvSquare", fInvSquare);
68 }
69
70private:
71 SkPoint fPoint;
72 SkScalar fConstant;
73 SkScalar fInvSquare;
74};
75
76class SkOrientAlongVelocityAffector : public SkParticleAffector {
77public:
78 SkOrientAlongVelocityAffector() {}
79
80 REFLECTED(SkOrientAlongVelocityAffector, SkParticleAffector)
81
82 void apply(SkParticleUpdateParams& params, SkParticlePoseAndVelocity& pv) override {
83 SkVector heading = pv.fVelocity.fLinear;
84 if (!heading.normalize()) {
85 heading.set(0, -1);
86 }
87 pv.fPose.fHeading = heading;
88 }
89
90 void visitFields(SkFieldVisitor*) override {}
91};
92
Brian Osman8b6283f2019-02-14 16:55:21 -050093class SkSizeAffector : public SkParticleAffector {
Brian Osman7c979f52019-02-12 13:27:51 -050094public:
Brian Osman8b6283f2019-02-14 16:55:21 -050095 SkSizeAffector(const SkCurve& curve = 1.0f) : fCurve(curve) {}
Brian Osman7c979f52019-02-12 13:27:51 -050096
Brian Osman8b6283f2019-02-14 16:55:21 -050097 REFLECTED(SkSizeAffector, SkParticleAffector)
Brian Osman7c979f52019-02-12 13:27:51 -050098
99 void apply(SkParticleUpdateParams& params, SkParticlePoseAndVelocity& pv) override {
Brian Osman8b6283f2019-02-14 16:55:21 -0500100 pv.fPose.fScale = fCurve.eval(params.fParticleT, *params.fStableRandom);
Brian Osman7c979f52019-02-12 13:27:51 -0500101 }
102
103 void visitFields(SkFieldVisitor* v) override {
Brian Osman8b6283f2019-02-14 16:55:21 -0500104 v->visit("Curve", fCurve);
Brian Osman7c979f52019-02-12 13:27:51 -0500105 }
106
107private:
Brian Osman8b6283f2019-02-14 16:55:21 -0500108 SkCurve fCurve;
Brian Osman7c979f52019-02-12 13:27:51 -0500109};
110
111void SkParticleAffector::RegisterAffectorTypes() {
112 REGISTER_REFLECTED(SkParticleAffector);
Brian Osman8b6283f2019-02-14 16:55:21 -0500113 REGISTER_REFLECTED(SkLinearVelocityAffector);
Brian Osman7c979f52019-02-12 13:27:51 -0500114 REGISTER_REFLECTED(SkPointForceAffector);
115 REGISTER_REFLECTED(SkOrientAlongVelocityAffector);
Brian Osman8b6283f2019-02-14 16:55:21 -0500116 REGISTER_REFLECTED(SkSizeAffector);
Brian Osman7c979f52019-02-12 13:27:51 -0500117}
118
Brian Osman8b6283f2019-02-14 16:55:21 -0500119sk_sp<SkParticleAffector> SkParticleAffector::MakeLinearVelocity(const SkCurve& angle,
120 const SkCurve& strength,
121 bool force) {
122 return sk_sp<SkParticleAffector>(new SkLinearVelocityAffector(angle, strength, force));
Brian Osman7c979f52019-02-12 13:27:51 -0500123}
124
Brian Osman8b6283f2019-02-14 16:55:21 -0500125sk_sp<SkParticleAffector> SkParticleAffector::MakePointForce(SkPoint point, SkScalar constant,
126 SkScalar invSquare) {
Brian Osman7c979f52019-02-12 13:27:51 -0500127 return sk_sp<SkParticleAffector>(new SkPointForceAffector(point, constant, invSquare));
128}
129
Brian Osman8b6283f2019-02-14 16:55:21 -0500130sk_sp<SkParticleAffector> SkParticleAffector::MakeOrientAlongVelocity() {
Brian Osman7c979f52019-02-12 13:27:51 -0500131 return sk_sp<SkParticleAffector>(new SkOrientAlongVelocityAffector());
132}
Brian Osman8b6283f2019-02-14 16:55:21 -0500133
134sk_sp<SkParticleAffector> SkParticleAffector::MakeSizeAffector(const SkCurve& curve) {
135 return sk_sp<SkParticleAffector>(new SkSizeAffector(curve));
136}