This repository has been archived by the owner on Jun 25, 2019. It is now read-only.
/
02_forces.html
1449 lines (1056 loc) · 81.6 KB
/
02_forces.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<section data-type="chapter" id="_chapter_2_forces">
<h1>Chapter 2. Forces</h1>
<blockquote data-type="epigraph">
<p>“Don’t underestimate the Force.”</p>
<p data-type="attribution">— Darth Vader</p>
</blockquote>
<a data-primary="forces" data-type="indexterm"></a>
<p>In the final example of Chapter 1, we saw how we could calculate a dynamic acceleration based on a vector pointing from a circle on the screen to the mouse position. The resulting motion resembled a magnetic attraction between circle and mouse, as if some <em>force</em> were pulling the circle in towards the mouse. In this chapter we will formalize our understanding of the concept of a force and its relationship to acceleration. Our goal, by the end of this chapter, is to understand how to make multiple objects move around the screen and respond to a variety of environmental forces.</p>
<section data-type="sect1" id="chapter02_section1">
<h2>2.1 Forces and Newton’s Laws of Motion</h2>
<a data-primary="forces" data-secondary="Newton's laws of motion" data-type="indexterm"></a> <a data-primary="Newton" data-secondary="Isaac" data-type="indexterm"></a>
<p>Before we begin examining the practical realities of simulating forces in code, let’s take a conceptual look at what it means to be a force in the real world. Just like the word “vector,” “force” is often used to mean a variety of things. It can indicate a powerful intensity, as in “She pushed the boulder with great force” or “He spoke forcefully.” The definition of <strong><em>force</em></strong> that we care about is much more formal and comes from Isaac Newton’s laws of motion:</p>
<a data-primary="forces" data-secondary="defined" data-type="indexterm"></a>
<p><span class="highlight">A force is a vector that causes an object with mass to accelerate.</span></p>
<p>The good news here is that we recognize the first part of the definition: <em>a force is a vector</em>. Thank goodness we just spent a whole chapter learning what a vector is and how to program with <code>PVector</code><code>s</code>!</p>
<p>Let’s look at Newton’s three laws of motion in relation to the concept of a force.</p>
<section data-type="sect2" id="_newton_s_first_law">
<h3>Newton’s First Law</h3>
<a data-primary="Newton's first law" data-type="indexterm"></a>
<p>Newton’s first law is commonly stated as:</p>
<p><span class="highlight">An object at rest stays at rest and an object in motion stays in motion.</span></p>
<p>However, this is missing an important element related to forces. We could expand it by stating:</p>
<p><span class="highlight">An object at rest stays at rest and an object in motion stays in motion at a constant speed and direction unless acted upon by an unbalanced force.</span></p>
<a data-primary="Aristotle" data-type="indexterm"></a>
<p>By the time Newton came along, the prevailing theory of motion—formulated by Aristotle—was nearly two thousand years old. It stated that if an object is moving, some sort of force is required to keep it moving. Unless that moving thing is being pushed or pulled, it will simply slow down or stop. Right?</p>
<a data-primary="equilibrium" data-type="indexterm"></a> <a data-primary="forces" data-secondary="equilibrium" data-type="indexterm"></a> <a data-primary="forces" data-secondary="terminal velocity" data-type="indexterm"></a> <a data-primary="terminal velocity" data-type="indexterm"></a>
<p>This, of course, is not true. In the absence of any forces, no force is required to keep an object moving. An object (such as a ball) tossed in the earth’s atmosphere slows down because of air resistance (a force). An object’s velocity will only remain constant in the absence of any forces or if the forces that act on it cancel each other out, i.e. the net force adds up to zero. This is often referred to as <strong><em>equilibrium</em></strong>. The falling ball will reach a terminal velocity (that stays constant) once the force of air resistance equals the force of gravity.</p>
<figure id="chapter02_figure1"><img alt="Figure 2.1: The pendulum doesn't move because all the forces cancel each other out (add up to a net force of zero)." src="chapter02/ch02_01.png" />
<figcaption>Figure 2.1: The pendulum doesn't move because all the forces cancel each other out (add up to a net force of zero). </figcaption>
</figure>
<p>In our Processing world, we could restate Newton’s first law as follows:</p>
<a data-primary="Newton's first law" data-secondary="PVector class and" data-type="indexterm"></a> <a data-primary="PVector class (Processing)" data-secondary="Newton's first law and" data-type="indexterm"></a>
<p><span class="highlight">An object’s PVector velocity will remain constant if it is in a state of equilibrium.</span></p>
<p>Skipping Newton’s second law (arguably the most important law for our purposes) for a moment, let’s move on to the third law.</p>
<a data-primary="Newton's third law" data-type="indexterm"></a>
</section>
<section data-type="sect2" id="_newton_s_third_law">
<h3>Newton’s Third Law</h3>
<p>This law is often stated as:</p>
<p><span class="highlight">For every action there is an equal and opposite reaction.</span></p>
<p>This law frequently causes some confusion in the way that it is stated. For one, it sounds like one force causes another. Yes, if you push someone, that someone may <em>actively</em> decide to push you back. But this is not the action and reaction we are talking about with Newton’s third law.</p>
<p>Let’s say you push against a wall. The wall doesn’t actively decide to push back on you. There is no “origin” force. Your push simply includes both forces, referred to as an “action/reaction pair.”</p>
<p>A better way of stating the law might be:</p>
<p><span class="highlight">Forces always occur in pairs. The two forces are of equal strength, but in opposite directions.</span></p>
<p>Now, this still causes confusion because it sounds like these forces would always cancel each other out. This is not the case. Remember, the forces act on different objects. And just because the two forces are equal, it doesn’t mean that the movements are equal (or that the objects will stop moving).</p>
<p>Try pushing on a stationary truck. Although the truck is far more powerful than you, unlike a moving one, a stationary truck will never overpower you and send you flying backwards. The force you exert on it is equal and opposite to the force exerted on your hands. The outcome depends on a variety of other factors. If the truck is a small truck on an icy downhill, you’ll probably be able to get it to move. On the other hand, if it’s a very large truck on a dirt road and you push hard enough (maybe even take a running start), you could injure your hand.</p>
<p>And if you are wearing roller skates when you push on that truck?</p>
<figure id="chapter02_figure2"><img alt="Figure 2.2" src="chapter02/ch02_02.png" />
<figcaption>Figure 2.2</figcaption>
</figure>
<p>You’ll accelerate away from the truck, sliding along the road while the truck stays put. Why do you slide but not the truck? For one, the truck has a much larger mass (which we’ll get into with Newton’s second law). There are other forces at work too, namely the friction of the truck’s tires and your roller skates against the road.</p>
</section>
<section data-type="sect2" id="_newton_s_third_law_as_seen_through_the_eyes_of_processing">
<h3>Newton’s Third Law (as seen through the eyes of Processing)</h3>
<a data-primary="Newton's third law" data-secondary="PVector class and" data-type="indexterm"></a> <a data-primary="PVector class (Processing)" data-secondary="Newton's third law and" data-type="indexterm"></a>
<p><span class="highlight">If we calculate a PVector f that is a force of object A on object B, we must also apply the force—PVector.mult(f,-1);—that B exerts on object A.</span></p>
<p>We’ll see that in the world of Processing programming, we don’t always have to stay true to the above. Sometimes, such as in the case of <a href="#chapter02_example6">gravitational attraction between bodies</a>, we’ll want to model equal and opposite forces. Other times, such as when we’re simply saying, “Hey, there’s some wind in the environment,” we’re not going to bother to model the force that a body exerts back on the air. In fact, we’re not modeling the air at all! Remember, we are simply taking inspiration from the physics of the natural world, not simulating everything with perfect precision.</p>
</section>
</section>
<section data-type="sect1" id="chapter02_section2">
<h2>2.2 Forces and Processing—Newton’s Second Law as a Function</h2>
<a data-primary="acceleration" data-secondary="Newton's second law" data-type="indexterm"></a> <a data-primary="natural phenomena" data-secondary="Newton's second law" data-tertiary="modeling" data-type="indexterm"></a> <a data-primary="Newton's second law" data-type="indexterm"></a>
<p>And here we are at the most important law for the Processing programmer.</p>
<section data-type="sect2" id="_newton_s_second_law">
<h3>Newton’s Second Law</h3>
<p>This law is stated as:</p>
<p><span class="highlight">Force equals mass times acceleration.</span></p>
<p>Or:</p>
<div data-type="equation">\vec{F} = M \times \vec{A}</div>
<p>Why is this the most important law for us? Well, let’s write it a different way.</p>
<div data-type="equation">\vec{A} = \vec{F} / M</div>
<p>Acceleration is directly proportional to force and inversely proportional to mass. This means that if you get pushed, the harder you are pushed, the faster you’ll move (accelerate). The bigger you are, the slower you’ll move.</p>
<a data-primary="density" data-type="indexterm"></a> <a data-primary="mass" data-secondary="weight vs." data-type="indexterm"></a> <a data-primary="weight" data-secondary="mass vs." data-type="indexterm"></a>
<div data-type="note">
<h2>Weight vs. Mass</h2>
<ul>
<li>
<p>The <strong><em>mass</em></strong> of an object is a measure of the amount of matter in the object (measured in kilograms).</p>
</li>
<li>
<p><strong><em>Weight</em></strong>, though often mistaken for mass, is technically the force of gravity on an object. From Newton’s second law, we can calculate it as mass times the acceleration of gravity (<code>w</code> = <code>m</code> * <code>g</code>). Weight is measured in newtons.</p>
</li>
<li>
<p><strong><em>Density</em></strong> is defined as the amount of mass per unit of volume (grams per cubic centimeter, for example).</p>
</li>
</ul>
<p>Note that an object that has a mass of one kilogram on earth would have a mass of one kilogram on the moon. However, it would weigh only one-sixth as much.</p>
</div>
<p>Now, in the world of Processing, what is mass anyway? Aren’t we dealing with pixels? To start in a simpler place, let’s say that in our pretend pixel world, all of our objects have a mass equal to 1. <code>F</code>/ 1 = <code>F</code>. And so:</p>
<div data-type="equation">\vec{A} = \vec{F}</div>
<p>The acceleration of an object is equal to force. This is great news. After all, we saw in Chapter 1 that acceleration was the key to controlling the movement of our objects on screen. position is adjusted by velocity, and velocity by acceleration. Acceleration was where it all began. Now we learn that <em>force</em> is truly where it all begins.</p>
<p>Let’s take our <code>Mover</code> class, with position, velocity, and acceleration.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
class Mover {
PVector position;
PVector velocity;
PVector acceleration;
}</pre>
<p>Now our goal is to be able to add forces to this object, perhaps saying:</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
mover.applyForce(wind);</pre>
<p>or:</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
mover.applyForce(gravity);</pre>
<p>where wind and gravity are <code>PVector</code> objects. According to Newton’s second law, we could implement this function as follows.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
void applyForce(PVector force) {
//{!1} Newton's second law at its simplest.
acceleration = force;
}</pre>
</section>
</section>
<section data-type="sect1" id="chapter02_section3">
<h2>2.3 Force Accumulation</h2>
<a data-primary="forces" data-secondary="accumulation of" data-type="indexterm"></a>
<p>This looks pretty good. After all, <em>acceleration = force</em> is a literal translation of Newton’s second law (without mass). Nevertheless, there’s a pretty big problem here. Let’s return to what we are trying to accomplish: creating a moving object on the screen that responds to wind and gravity.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
mover.applyForce(wind);
mover.applyForce(gravity);
mover.update();
mover.display();</pre>
<p>Ok, let’s <em>be</em> the computer for a moment. First, we call <code>applyForce()</code> with wind. And so the <code>Mover</code> object’s acceleration is now assigned the <code>PVector</code> <code>wind</code>. Second, we call <code>applyForce()</code> with gravity. Now the <code>Mover</code> object’s acceleration is set to the gravity <code>PVector</code>. Third, we call <code>update()</code>. What happens in <code>update()</code>? Acceleration is added to velocity.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
velocity.add(acceleration);</pre>
<p>We’re not going to see any error in Processing, but zoinks! We’ve got a major problem. What is the value of acceleration when it is added to velocity? It is equal to the gravity force. Wind has been left out! If we call <code>applyForce()</code> more than once, it overrides each previous call. How are we going to handle more than one force?</p>
<a data-primary="force accumulation" data-type="indexterm"></a>
<p>The truth of the matter here is that we started with a simplified statement of Newton’s second law. Here’s a more accurate way to put it:</p>
<p><span class="highlight">Net Force equals mass times acceleration.</span></p>
<p>Or, acceleration is equal to the <em>sum of all forces</em> divided by mass. This makes perfect sense. After all, as we saw in Newton’s first law, if all the forces add up to zero, an object experiences an equilibrium state (i.e. no acceleration). Our implementation of this is through a process known as <strong><em>force accumulation</em></strong>. It’s actually very simple; all we need to do is add all of the forces together. At any given moment, there might be 1, 2, 6, 12, or 303 forces. As long as our object knows how to accumulate them, it doesn’t matter how many forces act on it.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
void applyForce(PVector force) {
//{!1} Newton's second law, but with force accumulation. We now add each force to acceleration, one at a time.
acceleration.add(force);
}</pre>
<p>Now, we’re not finished just yet. Force accumulation has one more piece. Since we’re adding all the forces together at any given moment, we have to make sure that we clear acceleration (i.e. set it to zero) before each time <code>update()</code> is called. Let’s think about wind for a moment. Sometimes the wind is very strong, sometimes it’s weak, and sometimes there’s no wind at all. At any given moment, there might be a huge gust of wind, say, when the user holds down the mouse.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
if (mousePressed) {
PVector wind = new PVector(0.5, 0);
mover.applyForce(wind);
}</pre>
<a data-primary="acceleration" data-secondary="force accumulation and" data-type="indexterm"></a>
<p>When the user releases the mouse, the wind will stop, and according to Newton’s first law, the object will continue to move at a constant velocity. However, if we had forgotten to reset acceleration to zero, the gust of wind would still be in effect. Even worse, it would add onto itself from the previous frame, since we are accumulating forces! Acceleration, in our simulation, has no memory; it is simply calculated based on the environmental forces present at a moment in time. This is different than, say, position, which must remember where the object was in the previous frame in order to move properly to the next.</p>
<p>The easiest way to implement clearing the acceleration for each frame is to multiply the <code>PVector</code> by 0 at the end of <code>update()</code>.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
void update() {
velocity.add(acceleration);
position.add(velocity);
acceleration.mult(0);
}</pre>
<div data-type="exercise" id="chapter02_exercise1">
<h5>Exercise 2.1</h5>
<p>Using forces, simulate a helium-filled balloon floating upward and bouncing off the top of a window. Can you add a wind force that changes over time, perhaps according to Perlin noise?</p>
</div>
</section>
<section data-type="sect1" id="chapter02_section4">
<h2>2.4 Dealing with Mass</h2>
<a data-primary="mass" data-secondary="modeling" data-type="indexterm"></a> <a data-primary="natural phenomena" data-secondary="mass" data-tertiary="modeling" data-type="indexterm"></a>
<p>OK. We’ve got one tiny little addition to make before we are done with integrating forces into our <code>Mover</code> class and are ready to look at examples. After all, Newton’s second law is really <span data-type="equation">\vec{F} = M \times \vec{A}</span>, not <span data-type="equation">\vec{F} = \vec{A}</span>. Incorporating mass is as easy as adding an instance variable to our class, but we need to spend a little more time here because a slight complication will emerge.</p>
<p>First we just need to add mass.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
class Mover {
PVector position;
PVector velocity;
PVector acceleration;
//{!1} Adding mass as a float
float mass;
}</pre>
<a data-primary="mass" data-secondary="units of measurement" data-tertiary="defining" data-type="indexterm"></a>
<div data-type="note">
<h2>Units of Measurement</h2>
<p>Now that we are introducing mass, it’s important to make a quick note about units of measurement. In the real world, things are measured in specific units. We say that two objects are 3 meters apart, the baseball is moving at a rate of 90 miles per hour, or this bowling ball has a mass of 6 kilograms. As we’ll see later in this book, sometimes we will want to take real-world units into consideration. However, in this chapter, we’re going to ignore them for the most part. Our units of measurement are in pixels (“These two circles are 100 pixels apart”) and frames of animation (“This circle is moving at a rate of 2 pixels per frame”). In the case of mass, there isn’t any unit of measurement for us to use. We’re just going to make something up. In this example, we’re arbitrarily picking the number 10. There is no unit of measurement, though you might enjoy inventing a unit of your own, like “1 moog” or “1 yurkle.” It should also be noted that, for demonstration purposes, we’ll tie mass to pixels (drawing, say, a circle with a radius of 10). This will allow us to visualize the mass of an object. In the real world, however, size does not definitely indicate mass. A small metal ball could have a much higher mass than a large balloon due to its higher density.</p>
</div>
<p>Mass is a scalar (float), not a vector, as it’s just one number describing the amount of matter in an object. We could be fancy about things and compute the area of a shape as its mass, but it’s simpler to begin by saying, “Hey, the mass of this object is…um, I dunno…how about 10?”</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
Mover() {
position = new PVector(random(width), random(height));
velocity = new PVector(0, 0);
acceleration = new PVector(0, 0);
mass = 10.0;
}</pre>
<a data-primary="forces" data-secondary="applying to objects" data-type="indexterm"></a>
<p>This isn’t so great since things only become interesting once we have objects with varying mass, but it’ll get us started. Where does mass come in? We use it while applying Newton’s second law to our object.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
void applyForce(PVector force) {
//{!2} Newton's second law (with force accumulation and mass)
force.div(mass);
acceleration.add(force);
}</pre>
<p>Yet again, even though our code looks quite reasonable, we have a fairly major problem here. Consider the following scenario with two <code>Mover</code> objects, both being blown away by a wind force.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
Mover m1 = new Mover();
Mover m2 = new Mover();
PVector wind = new PVector(1,0);
m1.applyForce(wind);
m2.applyForce(wind);</pre>
<p>Again, let’s <em>be</em> the computer. Object <code>m1</code> receives the wind force—(1,0)—divides it by mass (10), and adds it to acceleration.</p>
<p><span class="formula">m1 equals wind force: (1,0)</span><br />
<span class="formula">Divided by mass of 10: (0.1,0)</span></p>
<a data-primary="object-oriented programming" data-secondary="references to vs. copies of objects" data-type="indexterm"></a>
<p>OK. Moving on to object <code>m2</code>. It also receives the wind force—(1,0). Wait. Hold on a second. What is the value of the wind force? Taking a closer look, the wind force is actually now—(0.1,0)!! Do you remember this little tidbit about working with objects? When you pass an object (in this case a <code>PVector</code>) into a function, you are passing a reference to that object. It’s not a copy! So if a function makes a change to that object (which, in this case, it does by dividing by mass) then that object is permanently changed! But we don’t want <code>m2</code> to receive a force divided by the mass of object <code>m1</code>. We want it to receive that force in its original state—(1,0). And so we must protect ourselves and make a copy of the <code>PVector</code> f before dividing it by mass. Fortunately, the <code>PVector</code> class has a convenient method for making a copy—<code>copy()</code>. <code>copy()</code> returns a new <code>PVector</code> object with the same data. And so we can revise <code>applyForce()</code> as follows:</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
void applyForce(PVector force) {
//{!1} Making a copy of the PVector before using it!
PVector f = force.copy();
f.div(mass);
acceleration.add(f);
}</pre>
<p>There’s another way we could write the above function, using the static method <code>div()</code>. For help with this exercise, review static methods in <a href="#chapter01_section9">Chapter 1</a>.</p>
<div data-type="exercise" id="chapter02_exercise2">
<h5>Exercise 2.2</h5>
<p>Rewrite the <code>applyForce()</code> method using the static method <code>div()</code> instead of <code>copy()</code>.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
void applyForce(PVector force) {
PVector f = _______.___(_____,____);
acceleration.add(f);
}</pre>
</div>
</section>
<section data-type="sect1" id="chapter02_section5">
<h2>2.5 Creating Forces</h2>
<a data-primary="forces" data-secondary="creating" data-type="indexterm"></a>
<p>Let’s take a moment to remind ourselves where we are. We know what a force is (a vector), and we know how to apply a force to an object (divide it by mass and add it to the object’s acceleration vector). What are we missing? Well, we have yet to figure out how we get a force in the first place. Where do forces come from?</p>
<p>In this chapter, we’ll look at two methods for creating forces in our Processing world.</p>
<a data-primary="natural phenomena" data-secondary="forces" data-tertiary="modeling" data-type="indexterm"></a>
<ol>
<li>
<p><strong>Make up a force!</strong> After all, you are the programmer, the creator of your world. There’s no reason why you can’t just make up a force and apply it.</p>
</li>
<li>
<p><strong>Model a force!</strong> Yes, forces exist in the real world. And physics textbooks often contain formulas for these forces. We can take these formulas, translate them into source code, and model real-world forces in Processing.</p>
</li>
</ol>
<p>The easiest way to make up a force is to just pick a number. Let’s start with the idea of simulating wind. How about a wind force that points to the right and is fairly weak? Assuming a <code>Mover</code> object m, our code would look like:</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
PVector wind = new PVector(0.01,0);
m.applyForce(wind);</pre>
<p>The result isn’t terribly interesting, but it is a good place to start. We create a <code>PVector</code> object, initialize it, and pass it into an object (which in turn will apply it to its own acceleration). If we wanted to have two forces, perhaps wind and gravity (a bit stronger, pointing down), we might write the following:</p>
<figure class="screenshot" data-pde="processingjs/chapter02/_2_1_forces/_2_1_forces.pde processingjs/chapter02/_2_1_forces/Mover.pde"><img alt="ch02 ex01" src="chapter02/ch02_ex01.png" />
<figcaption> </figcaption>
</figure>
<div data-type="example">
<h5>Example 2.1: Forces</h5>
</div>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
PVector wind = new PVector(0.01, 0);
PVector gravity = new PVector(0, 0.1);
m.applyForce(wind);
m.applyForce(gravity);</pre>
<p>Now we have two forces, pointing in different directions with different magnitudes, both applied to object <code>m</code>. We’re beginning to get somewhere. We’ve now built a world for our objects in Processing, an environment to which they can actually respond.</p>
<p>Let’s look at how we could make this example a bit more exciting with many objects of varying mass. To do this, we’ll need a quick review of object-oriented programming. Again, we’re not covering all the basics of programming here (for that you can check out any of the intro Processing books listed in the introduction). However, since the idea of creating a world filled with objects is pretty fundamental to all the examples in this book, it’s worth taking a moment to walk through the steps of going from one object to many.</p>
<p>This is where we are with the <code>Mover</code> class as a whole. Notice how it is identical to the <code>Mover</code> class created in Chapter 1, with two additions—<code>mass</code> and a new <code>applyForce()</code> function.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
class Mover {
PVector position;
PVector velocity;
PVector acceleration;
//{!1} The object now has mass!
float mass;
Mover() {
//{!1} And for now, we'll just set the mass equal to 1 for simplicity.
mass = 1;
position = new PVector(30, 30);
velocity = new PVector(0, 0);
acceleration = new PVector(0, 0);
}
// Newton's second law.
void applyForce(PVector force) {
//{!2} Receive a force, divide by mass, and add to acceleration.
PVector f = PVector.div(force,mass);
acceleration.add(f);
}
void update() {
//{!2} Motion 101 from Chapter 1
velocity.add(acceleration);
position.add(velocity);
// Now add clearing the acceleration each time!
acceleration.mult(0);
}
void display() {
stroke(0);
fill(175);
//{!1} Scaling the size according to mass.
ellipse(position.x, position.y, mass*16, mass*16);
}
// Somewhat arbitrarily, we are deciding that an object bounces when it hits the edges of a window.
void checkEdges() {
if (position.x > width) {
position.x = width;
velocity.x *= -1;
} else if (position.x < 0) {
velocity.x *= -1;
position.x = 0;
}
if (position.y > height) {
//{!2} Even though we said we shouldn't touch position and velocity directly, there are some exceptions. Here we are doing so as a quick and easy way to reverse the direction of our object when it reaches the edge.
velocity.y *= -1;
position.y = height;
}
}
}</pre>
<p>Now that our class is set, we can choose to create, say, one hundred <code>Mover</code> objects with an array.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
Mover[] movers = new Mover[100];</pre>
<p>And then we can initialize all of those <code>Mover</code> objects in <code>setup()</code> with a loop.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
void setup() {
for (int i = 0; i < movers.length; i++) {
movers[i] = new Mover();
}
}</pre>
<p>But now we have a small issue. If we refer back to the <code>Mover</code> object’s constructor…</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
Mover() {
//{!2} Every object has a mass of 1 and a position of (30, 30).
mass = 1;
position = new PVector(30, 30);
velocity = new PVector(0, 0);
acceleration = new PVector(0, 0);
}</pre>
<a data-primary="constructor" data-secondary="arguments" data-tertiary="adding to" data-type="indexterm"></a>
<p>…we discover that every <code>Mover</code> object is made exactly the same way. What we want are <code>Mover</code> objects of varying mass that start at varying positions. Here is where we need to increase the sophistication of our constructor by adding arguments.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
Mover(float m, float x , float y) {
//{!2} Now setting these variables with arguments
mass = m;
position = new PVector(x, y);
velocity = new PVector(0, 0);
acceleration = new PVector(0, 0);
}</pre>
<p>Notice how the mass and position are no longer set to hardcoded numbers, but rather initialized via arguments passed through the constructor. This means we can create a variety of <code>Mover</code> objects: big ones, small ones, ones that start on the left side of the screen, ones that start on the right, etc.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
// A big Mover on the left side of the window
Mover m1 = new Mover(10, 0, height/2);
// A small Mover on the right side of the window
Mover m1 = new Mover(0.1, width, height/2);</pre>
<p>With an array, however, we want to initialize all of the objects with a loop.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
void setup() {
for (int i = 0; i < movers.length; i++) {
// Initializing many Mover objects, all with random mass (and all starting at 0,0)
movers[i] = new Mover(random(0.1, 5), 0, 0);
}
}</pre>
<p>For each mover created, the mass is set to a random value between 0.1 and 5, the starting x-position is set to 0, and the starting y-position is set to 0. Certainly, there are all sorts of ways we might choose to initialize the objects; this is just a demonstration of one possibility.</p>
<p>Once the array of objects is declared, created, and initialized, the rest of the code is simple. We run through every object, hand them each the forces in the environment, and enjoy the show.</p>
<figure class="screenshot" data-pde="processingjs/chapter02/_2_2_forces_many/_2_2_forces_many.pde processingjs/chapter02/_2_2_forces_many/Mover.pde"><img alt="ch02 ex02" src="chapter02/ch02_ex02.png" />
<figcaption> </figcaption>
</figure>
<div data-type="example">
<h5>Example 2.2: Forces acting on many objects</h5>
</div>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
void draw() {
background(255);
PVector wind = new PVector(0.01,0);
//{!1} Make up two forces.
PVector gravity = new PVector(0,0.1);
//{!3} Loop through all objects and apply both forces to each object.
for (int i = 0; i < movers.length; i++) {
movers[i].applyForce(wind);
movers[i].applyForce(gravity);
movers[i].update();
movers[i].display();
movers[i].checkEdges();
}
}</pre>
<p>Note how in the above image, the smaller circles reach the right of the window faster than the larger ones. This is because of our formula: <em>acceleration = force divided by mass</em>. The larger the mass, the smaller the acceleration.</p>
<div data-type="exercise" id="chapter02_exercise3">
<h5>Exercise 2.3</h5>
<p>Instead of objects bouncing off the edge of the wall, create an example in which an invisible force pushes back on the objects to keep them in the window. Can you weight the force according to how far the object is from an edge—i.e., the closer it is, the stronger the force?</p>
</div>
</section>
<section data-type="sect1" id="chapter02_section6">
<h2>2.6 Gravity on Earth and Modeling a Force</h2>
<a data-primary="forces" data-secondary="gravity" data-tertiary="modeling" data-type="indexterm"></a> <a data-primary="Galileo" data-type="indexterm"></a> <a data-primary="natural phenomena" data-secondary="gravity" data-type="indexterm"></a>
<p>You may have noticed something woefully inaccurate about this last example. The smaller the circle, the faster it falls. There is a logic to this; after all, we just stated (according to Newton’s second law) that the smaller the mass, the higher the acceleration. But this is not what happens in the real world. If you were to climb to the top of the Leaning Tower of Pisa and drop two balls of different masses, which one will hit the ground first? According to legend, Galileo performed this exact test in 1589, discovering that they fell with the same acceleration, hitting the ground at the same time. Why is this? As we will see later in this chapter, the force of gravity is calculated relative to an object’s mass. The bigger the object, the stronger the force. So if the force is scaled according to mass, it is canceled out when acceleration is divided by mass. We can implement this in our sketch rather easily by multiplying our made-up gravity force by mass.</p>
<figure class="screenshot" data-pde="processingjs/chapter02/_2_3_forces_many_realgravity/_2_3_forces_many_realgravity.pde processingjs/chapter02/_2_3_forces_many_realgravity/Mover.pde"><img alt="ch02 ex03" src="chapter02/ch02_ex03.png" />
<figcaption> </figcaption>
</figure>
<div data-type="example">
<h5>Example 2.3: Gravity scaled by mass</h5>
</div>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
for (int i = 0; i < movers.length; i++) {
PVector wind = new PVector(0.001,0);
float m = movers[i].mass;
//{!1} Scaling gravity by mass to be more accurate
PVector gravity = new PVector(0, 0.1*m);
movers[i].applyForce(wind);
movers[i].applyForce(gravity);
movers[i].update();
movers[i].display();
movers[i].checkEdges();
}</pre>
<p>While the objects now fall at the same rate, because the strength of the wind force is independent of mass, the smaller objects still accelerate to the right more quickly.</p>
<p>Making up forces will actually get us quite far. The world of Processing is a pretend world of pixels and you are its master. So whatever you deem appropriate to be a force, well by golly, that’s the force it should be. Nevertheless, there may come a time where you find yourself wondering: “But how does it really all work?”</p>
<a data-primary="forces" data-secondary="models of" data-tertiary="building" data-type="indexterm"></a> <a data-primary="natural phenomena" data-secondary="physics (real world)" data-tertiary="modeling" data-type="indexterm"></a> <a data-primary="physics" data-secondary="modeling" data-type="indexterm"></a>
<p>Open up any high school physics textbook and you will find some diagrams and formulas describing many different forces—gravity, electromagnetism, friction, tension, elasticity, and more. In this chapter we’re going to look at two forces—friction and gravity. The point we’re making here is not that friction and gravity are fundamental forces that you always need to have in your Processing sketches. Rather, we want to evaluate these two forces as case studies for the following process:</p>
<ul>
<li>
<p>Understanding the concept behind a force</p>
</li>
<li>
<p>Deconstructing the force’s formula into two parts:</p>
<ul>
<li>
<p>How do we compute the force’s direction?</p>
</li>
<li>
<p>How do we compute the force’s magnitude?</p>
</li>
</ul>
</li>
<li>
<p>Translating that formula into Processing code that calculates a <code>PVector</code> to be sent through our <code>Mover</code><code>'s</code> <code>applyForce()</code> function</p>
</li>
</ul>
<p>If we can follow the above steps with two forces, then hopefully if you ever find yourself Googling “atomic nuclei weak nuclear force” at 3 a.m., you will have the skills to take what you find and adapt it for Processing.</p>
<a data-primary="formulae" data-secondary="evaluating in code" data-type="indexterm"></a>
<div data-type="note">
<h2>Dealing with formulae</h2>
<p>OK, in a moment we’re going to write out the formula for friction. This isn’t the first time we’ve seen a formula in this book; we just finished up our discussion of Newton’s second law, <span data-type="equation">\vec{F} = M \times \vec{A}</span> (or force = mass * acceleration). We didn’t spend a lot of time worrying about this formula because it’s a nice and simple one. Nevertheless, it’s a scary world out there. Just take a look at the equation for a “normal” distribution, which we covered (without looking at the formula) in the <a href="#intro_section4">Introduction</a>.</p>
<div class="equation-w-sqrt-small">
<div data-type="equation">\frac{1}{\sigma\sqrt{2\pi}}e^{-\frac{(x-\mu)^2}{2\sigma^2}}</div>
</div>
<a data-primary="friction" data-secondary="formula for" data-type="indexterm"></a>
<p>What we’re seeing here is that formulas like to use a lot of symbols (quite often letters from the Greek alphabet). Let’s take a look at the formula for friction.</p>
<div data-type="equation">\vec{friction} = -\mu * N * \hat{\nu}</div>
<p>If it’s been a while since you’ve looked at a formula from a math or physics textbook, there are three key points that are important to cover before we move on.</p>
<ul>
<li>
<p><strong><em>Evaluate the right side, assign to the left side.</em></strong> This is just like in code! What we’re doing here is evaluating the right side of the equation and assigning it to the left. In the case above, we want to calculate the force of friction—the left side tells us what we want to calculate and the right side tells us how to do it.</p>
</li>
<li>
<p><strong><em>Are we talking about a vector or a scalar?</em></strong> It’s important for us to realize that in some cases, we’ll be looking at a vector; in others, a scalar. For example, in this case the force of friction is a vector. We can see that by the arrow above the word “friction.” It has a magnitude and direction. The right side of the equation also has a vector, as indicated by the symbol {unitv}, which in this case stands for the velocity unit vector.</p>
</li>
<li>
<p><strong><em>When symbols are placed next to each other, we mean for them to be multiplied.</em></strong> The formula above actually has four elements: -1, <em>μ</em>, <em>N</em>, and <span data-type="equation">\hat{v}</span>
. We want to multiply them together and read the formula as: <span data-type="equation">\vec{friction} = -1 * \mu * N * \hat{\nu}</span></p>
</li>
</ul>
</div>
</section>
<section data-type="sect1" id="chapter02_section7">
<h2>2.7 Friction</h2>
<a data-primary="forces" data-secondary="friction" data-tertiary="modeling" data-type="indexterm"></a> <a data-primary="friction" data-secondary="modeling with formulae" data-type="indexterm"></a> <a data-primary="natural phenomena" data-secondary="friction" data-type="indexterm"></a>
<p>Let’s begin with friction and follow our steps.</p>
<a data-primary="dissipative force" data-type="indexterm"></a>
<p>Friction is a <strong><em>dissipative force</em></strong>. A dissipative force is one in which the total energy of a system decreases when an object is in motion. Let’s say you are driving a car. When you press your foot down on the brake pedal, the car’s brakes use friction to slow down the motion of the tires. Kinetic energy (motion) is converted into thermal energy (heat). Whenever two surfaces come into contact, they experience friction. A complete model of friction would include separate cases for static friction (a body at rest against a surface) and kinetic friction (a body in motion against a surface), but for our purposes, we are only going to look at the kinetic case.</p>
<p>Here’s the formula for friction:</p>
<figure id="chapter02_figure3"><img alt="Figure 2.3" src="chapter02/ch02_03.png" />
<figcaption>Figure 2.3</figcaption>
</figure>
<a data-primary="friction" data-secondary="determining direction/magnitude of" data-type="indexterm"></a>
<p>It’s now up to us to separate this formula into two components that determine the direction of friction as well as the magnitude. Based on the diagram above, we can see that <em>friction points in the opposite direction of velocity.</em> In fact, that’s the part of the formula that says -1 * <span data-type="equation">\hat{v}</span>, or -1 times the velocity unit vector. In Processing, this would mean taking the velocity vector, normalizing it, and multiplying by -1.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
PVector friction = velocity.copy();
friction.normalize();
// Let’s figure out the direction of the friction force
// (a unit vector in the opposite direction of velocity).
friction.mult(-1);</pre>
<p>Notice two additional steps here. First, it’s important to make a copy of the velocity vector, as we don’t want to reverse the object’s direction by accident. Second, we normalize the vector. This is because the magnitude of friction is not associated with how fast it is moving, and we want to start with a friction vector of magnitude 1 so that it can easily be scaled.</p>
<a data-primary="mu (μ)" data-type="indexterm"></a> <a data-primary="coefficient of friction" data-type="indexterm"></a> <a data-primary="coefficient of friction" data-secondary="mu (μ)" data-type="indexterm"></a> <a data-primary="friction" data-secondary="mu (μ)" data-type="indexterm"></a> <a data-primary="friction" data-secondary="coefficient of friction" data-type="indexterm"></a>
<p>According to the formula, the magnitude is <code>μ</code> * <code>N</code>. <code>μ</code>, the Greek letter <em>mu</em> (pronounced “mew”), is used here to describe the <strong><em>coefficient of friction</em></strong>. The coefficient of friction establishes the strength of a friction force for a particular surface. The higher it is, the stronger the friction; the lower, the weaker. A block of ice, for example, will have a much lower coefficient of friction than, say, sandpaper. Since we’re in a pretend Processing world, we can arbitrarily set the coefficient based on how much friction we want to simulate.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
float c = 0.01;</pre>
<a data-primary="friction" data-secondary="normal force" data-type="indexterm"></a> <a data-primary="normal force" data-type="indexterm"></a>
<p>Now for the second part: <code>N</code>. <code>N</code> refers to the <strong><em>normal force</em></strong>, the force perpendicular to the object’s motion along a surface. Think of a vehicle driving along a road. The vehicle pushes down against the road with gravity, and Newton’s third law tells us that the road in turn pushes back against the vehicle. That’s the normal force. The greater the gravitational force, the greater the normal force. As we’ll see in the next section, gravity is associated with mass, and so a lightweight sports car would experience less friction than a massive tractor trailer truck. With the diagram above, however, where the object is moving along a surface at an angle, computing the normal force is a bit more complicated because it doesn’t point in the same direction as gravity. We’ll need to know something about angles and trigonometry.</p>
<p>All of these specifics are important; however, in Processing, a “good enough” simulation can be achieved without them. We can, for example, make friction work with the assumption that the normal force will always have a magnitude of 1. When we get into trigonometry in the next chapter, we’ll remember to return to this question and make our friction example a bit more sophisticated. Therefore:</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
float normal = 1;</pre>
<p>Now that we have both the magnitude and direction for friction, we can put it all together…</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
float c = 0.01;
float normal = 1;
//{!1} Let's figure out the magnitude of friction (really just an arbitrary constant).
float frictionMag = c * normal;
PVector friction = velocity.copy();
friction.mult(-1);
friction.normalize();
// Take the unit vector and multiply it by magnitude and we have our force vector!
friction.mult(frictionMag);</pre>
<p>…and add it to our “forces” example, where many objects experience wind, gravity, and now friction:</p>
<figure class="two-col" data-pde="processingjs/chapter02/_2_4_forces_nofriction/_2_4_forces_nofriction.pde processingjs/chapter02/_2_4_forces_nofriction/Mover.pde"><img alt="No friction" src="chapter02/ch02_ex04a.png" />
<figcaption>No friction </figcaption>
</figure>
<figure class="two-col" data-pde="processingjs/chapter02/_2_4_forces_friction/_2_4_forces_friction.pde processingjs/chapter02/_2_4_forces_friction/Mover.pde"><img alt="With friction" src="chapter02/ch02_ex04b.png" />
<figcaption>With friction </figcaption>
</figure>
<div data-type="example">
<h5>Example 2.4: Including friction</h5>
</div>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
void draw() {
background(255);
PVector wind = new PVector(0.001, 0);
//{!1} We could scale by mass to be more accurate.
PVector gravity = new PVector(0, 0.1);
for (int i = 0; i < movers.length; i++) {
//{!5 .bold}
float c = 0.01;
PVector friction = movers[i].velocity.get();
friction.mult(-1);
friction.normalize();
friction.mult(c);
//{!1 .bold} Apply the friction force vector to the object.
movers[i].applyForce(friction);
movers[i].applyForce(wind);
movers[i].applyForce(gravity);
movers[i].update();
movers[i].display();
movers[i].checkEdges();
}
}</pre>
<p>Running this example, you’ll notice that the circles don’t even make it to the right side of the window. Since friction continuously pushes against the object in the opposite direction of its movement, the object continuously slows down. This can be a useful technique or a problem depending on the goals of your visualization.</p>
<div data-type="exercise" id="chapter02_exercise4">
<h5>Exercise 2.4</h5>
<p>Create pockets of friction in a Processing sketch so that objects only experience friction when crossing over those pockets. What if you vary the strength (friction coefficient) of each area? What if you make some pockets feature the opposite of friction—i.e., when you enter a given pocket you actually speed up instead of slowing down?</p>
</div>
</section>
<section data-type="sect1" id="chapter02_section8">
<h2>2.8 Air and Fluid Resistance</h2>
<figure id="chapter02_figure4"><img alt="Figure 2.4" src="chapter02/ch02_04.png" />
<figcaption>Figure 2.4</figcaption>
</figure>
<a data-primary="drag force" data-type="indexterm"></a> <a data-primary="fluid resistance" data-secondary="modeling" data-type="indexterm"></a> <a data-primary="forces" data-secondary="fluid resistance" data-type="indexterm"></a> <a data-primary="natural phenomena" data-secondary="fluid resistance" data-tertiary="modeling" data-type="indexterm"></a> <a data-primary="viscous force" data-type="indexterm"></a>
<p>Friction also occurs when a body passes through a liquid or gas. This force has many different names, all really meaning the same thing: <em>viscous force</em>, <em>drag force</em>, <em>fluid resistance</em>. While the result is ultimately the same as our previous friction examples (the object slows down), the way in which we calculate a drag force will be slightly different. Let’s look at the formula:</p>
<div data-type="equation">F_d = - \frac{1}{2}\rho\nu^2 A C_d\hat{\nu}</div>
<p>Now let’s break this down and see what we really need for an effective simulation in Processing, making ourselves a much simpler formula in the process.</p>
<ul>
<li>
<p><span data-type="equation">F_d</span> refers to <em>drag force</em>, the vector we ultimately want to compute and pass into our <code>applyForce()</code> function.</p>
</li>
<li>
<p>- 1/2 is a constant: -0.5. This is fairly irrelevant in terms of our Processing world, as we will be making up values for other constants anyway. However, the fact that it is negative is important, as it tells us that the force is in the opposite direction of velocity (just as with friction).</p>
</li>
</ul>
<a data-primary="rho (ρ)" data-type="indexterm"></a> <a data-primary="friction" data-secondary="rho (ρ)" data-type="indexterm"></a>
<ul>
<li>
<p><span data-type="equation">\rho</span> is the Greek letter <em>rho</em>, and refers to the density of the liquid, something we don’t need to worry about. We can simplify the problem and consider this to have a constant value of 1.</p>
</li>
<li>
<p><span data-type="equation">v</span> refers to the speed of the object moving. OK, we’ve got this one! The object’s speed is the magnitude of the velocity vector: <code>velocity.mag()</code>. And <span data-type="equation">v^2</span> just means <span data-type="equation">v</span> squared or <span data-type="equation">v \times v</span>.</p>
</li>
<li>
<p><span data-type="equation">A</span> refers to the frontal area of the object that is pushing through the liquid (or gas). An aerodynamic Lamborghini, for example, will experience less air resistance than a boxy Volvo. Nevertheless, for a basic simulation, we can consider our object to be spherical and ignore this element.</p>
</li>
<li>
<p><span data-type="equation">C_d</span> is the coefficient of drag, exactly the same as the coefficient of friction (μ). This is a constant we’ll determine based on whether we want the drag force to be strong or weak.</p>
</li>
<li>
<p><span data-type="equation">\hat{v}</span> Look familiar? It should. This refers to the velocity unit vector, i.e. <code>velocity.normalize()</code>. Just like with friction, drag is a force that points in the opposite direction of velocity.</p>
</li>
</ul>
<p>Now that we’ve analyzed each of these components and determined what we need for a simple simulation, we can reduce our formula to:</p>
<figure id="chapter02_figure5"><img alt="Figure 2.5: Our simplified drag force formula" src="chapter02/ch02_05.png" />
<figcaption>Figure 2.5: Our simplified drag force formula </figcaption>
</figure>
<p>or:</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
float c = 0.1;
float speed = velocity.mag();
//{!1} Part 1 of our formula (magnitude): Cd * v2
float dragMagnitude = c * speed * speed;
PVector drag = velocity.copy();
//{!1} Part 2 of our formula (direction): -1 * velocity
drag.mult(-1);
drag.normalize();
// Magnitude and direction together!
drag.mult(dragMagnitude);</pre>
<a data-primary="friction" data-secondary="applying to an object" data-type="indexterm"></a>
<p>Let’s implement this force in our <code>Mover</code> class example with one addition. When we wrote our friction example, the force of friction was always present. Whenever an object was moving, friction would slow it down. Here, let’s introduce an element to the environment—a “liquid” that the <code>Mover</code> objects pass through. The <code>Liquid</code> object will be a rectangle and will know about its position, width, height, and “coefficient of drag”—i.e., is it easy for objects to move through it (like air) or difficult (like molasses)? In addition, it should include a function to draw itself on the screen (and two more functions, which we’ll see in a moment).</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
class Liquid {
float x, y, w, h;
//{!1} The liquid object includes a variable defining its coefficient of drag.
float c;
Liquid(float x_, float y_, float w_, float h_, float c_) {
x = x_;
y = y_;
w = w_;
h = h_;
c = c_;
}
void display() {
noStroke();
fill(175);
rect(x, y, w, h);
}
}</pre>
<p>The main program will now include a <code>Liquid</code> object reference as well as a line of code that initializes that object.</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
Liquid liquid;
void setup() {
//{!1} Initialize a Liquid object. Note the coefficient is low (0.1), otherwise the object would come to a halt fairly quickly (which may someday be the effect you want).
liquid = new Liquid(0, height/2, width, height/2, 0.1);
}</pre>
<p>Now comes an interesting question: how do we get the <code>Mover</code> object to talk to the <code>Liquid</code> object? In other words, we want to execute the following:</p>
<p><em>When a mover passes through a liquid it experiences a drag force.</em></p>
<p>…or in object-oriented speak (assuming we are looping through an array of <code>Mover</code> objects with index i):</p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
// If a Mover is inside a Liquid, apply the drag force.
if (liquid.contains(movers[i])) {
liquid[i].drag(movers[i]);
}</pre>
<p>The above code tells us that we need to add two functions to the <code>Liquid</code> class: (1) a function that determines if a <code>Mover</code> object is inside the <code>Liquid</code> object, and (2) a function that computes and applies a drag force on the <code>Mover</code> object.</p>
The first is easy; we can simply use a boolean expressionto determine if the position vector rests inside the rectangle defined by the liquid.
<pre data-code-language="java" data-type="programlisting" class="codesplit">
boolean contains(Mover m) {
PVector pos = m.position;
//{.offset-top} This boolean expression determines if the PVector position is inside the rectangle defined by the Liquid class.
return pos.x > x && pos.x < x + w && pos.y > y && pos.y < y + h;
}</pre>
<p>The <code>drag()</code> function is a bit more complicated; however, we’ve written the code for it already. This is simply an implementation of our formula. The drag force is equal to <em>the coefficient of drag multiplied by the speed of the <code>Mover</code> squared in the opposite direction of velocity!</em></p>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
void drag(Mover m) {
float speed = m.velocity.mag();
// The force's magnitude: Cd * v~2~
float dragMagnitude = c * speed * speed;
// The force's direction: -1 * velocity
PVector drag = m.velocity.copy();
// Finalize the force: magnitude and direction together.
drag.setMag(dragMagnitude);
//{!1} Apply the force.
m.applyForce(drag);
}</pre>
<p>And with these two functions added to the <code>Liquid</code> class, we’re ready to put it all together in the main tab:</p>
<figure class="screenshot" data-pde="processingjs/chapter02/_2_5_fluidresistance/_2_5_fluidresistance.pde processingjs/chapter02/_2_5_fluidresistance/Liquid.pde processingjs/chapter02/_2_5_fluidresistance/Mover.pde"><img alt="ch02 ex05" src="chapter02/ch02_ex05.png" />
<figcaption> </figcaption>
</figure>
<div data-type="example">
<h5>Example 2.5: Fluid Resistance</h5>
</div>
<pre data-code-language="java" data-type="programlisting" class="codesplit">
Mover[] movers = new Mover[100];
Liquid liquid;
void setup() {
size(360, 640);
for (int i = 0; i < movers.length; i++) {
movers[i] = new Mover(random(0.1,5),0,0);
}
liquid = new Liquid(0, height/2, width, height/2, 0.1);
}
void draw() {
background(255);
liquid.display();
for (int i = 0; i < movers.length; i++) {
if (liquid.contains(movers[i])) {
liquid.drag(movers[i]);
}
//{!2} Note that we are scaling gravity according to mass.
float m = 0.1 * movers[i].mass;
PVector gravity = new PVector(0, m);
movers[i].applyForce(gravity);
movers[i].update();
movers[i].display();
movers[i].checkEdges();
}
}</pre>
<p>Running the example, you should notice that we are simulating balls falling into water. The objects only slow down when crossing through the gray area at the bottom of the window (representing the liquid). You’ll also notice that the smaller objects slow down a great deal more than the larger objects. Remember Newton’s second law? <code>A</code> = <code>F</code> / <code>M</code>. Acceleration equals force <em>divided</em> by mass. A massive object will accelerate less. A smaller object will accelerate more. In this case, the acceleration we’re talking about is the “slowing down” due to drag. The smaller objects will slow down at a greater rate than the larger ones.</p>
<div data-type="exercise" id="chapter02_exercise5">
<h5>Exercise 2.5</h5>
<p>Take a look at our formula for drag again: <strong><em>drag force = coefficient * speed * speed</em></strong>. The faster an object moves, the greater the drag force against it. In fact, an object not moving in water experiences no drag at all. Expand the example to drop the balls from different heights. How does this affect the drag as they hit the water?</p>
</div>
<div data-type="exercise" id="chapter02_exercise6">
<h5>Exercise 2.6</h5>
<p>The formula for drag also included surface area. Can you create a simulation of boxes falling into water with a drag force dependent on the length of the side hitting the water?</p>
</div>
<div data-type="exercise" id="chapter02_exercise7">
<h5>Exercise 2.7</h5>
<p>Fluid resistance does not only work opposite to the velocity vector, but also perpendicular to it. This is known as “lift-induced drag” and will cause an airplane with an angled wing to rise in altitude. Try creating a simulation of lift.</p>
</div>
</section>
<section data-type="sect1" id="chapter02_section9">
<h2>2.9 Gravitational Attraction</h2>
<a data-primary="gravity" data-secondary="modeling" data-type="indexterm"></a> <a data-primary="natural phenomena" data-secondary="gravity" data-type="indexterm"></a>
<figure class="half-width-right" id="chapter02_figure6"><img alt="Figure 2.6" src="chapter02/ch02_06.png" />
<figcaption>Figure 2.6</figcaption>
</figure>
<p>Probably the most famous force of all is gravity. We humans on earth think of gravity as an apple hitting Isaac Newton on the head. Gravity means that stuff falls down. But this is only <em>our</em> experience of gravity. In truth, just as the earth pulls the apple towards it due to a gravitational force, the apple pulls the earth as well. The thing is, the earth is just so freaking big that it overwhelms all the other gravity interactions. Every object with mass exerts a gravitational force on every other object. And there is a formula for calculating the strengths of these forces, as depicted in Figure 2.6.</p>
<p>Let’s examine this formula a bit more closely.</p>
<a data-primary="forces" data-secondary="universal gravitational constant" data-type="indexterm"></a> <a data-primary="gravity" data-secondary="universal gravitational constant" data-type="indexterm"></a> <a data-primary="universal gravitational constant" data-type="indexterm"></a>
<ul>
<li>
<p><code>F</code> refers to the gravitational force, the vector we ultimately want to compute and pass into our <code>applyForce()</code> function.</p>
</li>
<li>
<p><code>G</code> is the <em>universal gravitational constant</em>, which in our world equals 6.67428 x 10<sup>-11</sup> meters cubed per kilogram per second squared. This is a pretty important number if your name is Isaac Newton or Albert Einstein. It’s not an important number if you are a Processing programmer. Again, it’s a constant that we can use to make the forces in our world weaker or stronger. Just making it equal to one and ignoring it isn’t such a terrible choice either.</p>
</li>
<li>
<p><code>m<sub>1</sub></code> and <code>m<sub>2</sub></code> are the masses of objects 1 and 2. As we saw with Newton’s second law (<span data-type="equation">\vec{F} = M \times \vec{A}</span>), mass is also something we could choose to ignore. After all, shapes drawn on the screen don’t actually have a physical mass. However, if we keep these values, we can create more interesting simulations in which “bigger” objects exert a stronger gravitational force than smaller ones.</p>
</li>
<li>
<p><span data-type="equation">\hat{r}</span> refers to the unit vector pointing from object 1 to object 2. As we’ll see in a moment, we can compute this direction vector by subtracting the position of one object from the other.</p>
</li>
<li>
<p><span data-type="equation">r^2</span> refers to the distance between the two objects squared. Let’s take a moment to think about this a bit more. With everything on the top of the formula—<code>G</code>, <code>m<sub>1</sub></code>, <code>m<sub>2</sub></code>—the bigger its value, the stronger the force. Big mass, big force. Big <code>G</code>, big force. Now, when we divide by something, we have the opposite. The strength of the force is inversely proportional to the distance squared. The <em>farther away</em> an object is, the <em>weaker</em> the force; the <em>closer</em>, the <em>stronger</em>.</p>
</li>
</ul>
<p>Hopefully by now the formula makes some sense to us. We’ve looked at a diagram and dissected the individual components of the formula. Now it’s time to figure out how we translate the math into Processing code. Let’s make the following assumptions.</p>
<p>We have two objects, and:</p>
<a data-primary="gravity" data-secondary="implementing model of" data-type="indexterm"></a> <a data-primary="natural phenomena" data-secondary="gravity" data-type="indexterm"></a>
<ol>
<li>
<p>Each object has a position: <code>PVector position1</code> and <code>PVector position2</code>.</p>
</li>
<li>
<p>Each object has a mass: <code>float mass1</code> and <code>float mass2</code>.</p>
</li>
<li>
<p>There is a variable <code>float G</code> for the universal gravitational constant.</p>
</li>
</ol>
<p>Given these assumptions, we want to compute <code>PVector force</code>, the force of gravity. We’ll do it in two parts. First, we’ll compute the direction of the force <span data-type="equation">\hat{r}</span> in the formula above. Second, we’ll calculate the strength of the force according to the masses and distance.</p>
<figure class="half-width-right" id="chapter02_figure7"><img alt="Figure 2.7" src="chapter02/ch02_07.png" />
<figcaption>Figure 2.7</figcaption>
</figure>