Best Frenemy 7 – Calculating Distance in 3-space

In this post we’ll be doing some heavy math to calculate the distance between BF and EN. And to learn a little more gl, we’ll be displaying the data, like so:

Note the nice circular formation of the cubes – this is a stable “merry-go-round” configuration in which the friends chase each other in a circle while keeping their enemies at least one cube distant. See my last post for the starting positions and relationships that create this very nice pattern.

The first part of this patch is to make the stack of cubes in the upper left corner. We do this by dumping just the color information from the points table, and incrementing the y position of the cube placement using the index.

Show Max Compressed Code

<pre><code>
----------begin_max5_patcher----------
1243.3ocyYssaaiCD8YmuBtF4oEJFhWDIUeb2OihEAzVL1pQlzvhNWZQ+2Wp
gRwJMRIrI1JEAvjhhilYN7vCujebwr4KsOnqmi9B5qnYy9wEylAM0zvr1mmM
eq5gUUpZnayWY2tUabySBuyoevAsarN8WPFK5aktEqqVrQYJpzInZKxsQiVc
XotFU6TOh1cvgtei1.suWW6P1af506TqznxZzdqS4zEKPFsx8WctppznWYOX
.+Qaarr.7tc42tR10warFmQsUCu4esG1Wp2i9GaUQWGLG1VZpzNHiv8rpt76
fUX4hzi80dv004tV24iaOJnbkVy060qbAHjgIdCQrLQSQZ6On+qyJka0lRy5
QsfxAa3fQM17yKtn4mjO3fSwd08vPPyHvpaGDQIuDQEe9HZVN.LDoLVD84Vf
oPAibhQz0ZidumjhdDsxZ2WfVpp0EHqAUZJzODKmk+4ivTYF.Tx7XQ3maQKB
ex4r0Ukd0fpRu9PoAsQUcSrz1rOeP8JLO.QQSa4hdFbtXs9Ps.I8bUy554uD
3Xe9.Gl.3.OZxHICfJIHihy.SHryk94.fFcJAsAxeJvzn3SQ9az26SoWj9UV
UQCmYfrGOAYeWmCM4dbmNj5ygX5UIGDPohx.Lpcgg2K3rUWWqVqeI4Puys4Z
sQsrR6iUjuvTz64px0abMw0wlp2Zsdap2nJ7u.giUYCSHuO7lbRv6nvZICjt
R4ghSKSzuCwaQ2D9a.1H4cJ8yN+vSqxNIKr1IK6bLQ8u8pk3gvE1mIs4Fu9g
6UAGJl0a0O9YAa9dEJrkB5P.DcB.HxnDmj3HOc63BmeVDxpTO5yUVBZq8Nsy
htJcQN5Rle0GT3UzDz5pU1J6dzkXzkDzkTOgKKIbzB+TcVrBY+Aqi0MQMf0r
T1GRGa4AmyZFhwk9pKLdpVA7oroa+jefcUNxDqCeuDIGZqAxIXLl9pHSxwxR
iKFfRhOeJPvDBelmhDCAWuySam86.WrwfqF3IoUIJdzBmFDjH4mG7ppBsy5i
kgNrBdJN6L6UkrS9MjtCy8n4xiHUqQMo40EJmpEgZgnYyeR.Ulz1RWu9Jzum
5o+M2perWx0zxcppCsQqWH2ugCIimzTMUPvTLbvJNOGyZpwwYMEzbnPJCCiy
5FDGzWjw7EgvjBYyGBiwBL3JRFllSZpkkK.mjQIPoPHxhwczwbmTxEBvIXNM
SRfjDmRjzPpwB9QlEJy7OGi+Xild4XRC94qRYYhbZnpfIDPPHCoUa5wyhxaY
i4MtOOxygAmToDpPX9DN3DVvGoAeQIwkZoi5LFlxCrDrD2kYRYZJ78yw88Vy
.XLdiO5.WJmR4PFIxxjTfR1BtoKXAelJCdiIixYhQG0Rwo7.qOWPDz.PJSyC
CVA7iEfUeO56r1pduFlvVqtSWbsWCxOI+ZkysuzuJe3Vz6O8UucoFjqvsle5
TFaui85a0d8Fz818G055qPNEWMwGdSsrvE3PB2X1KVCA9Bv9I+k+MEvWro8m
Ce09raUWLzc1GzQ01Bcs+v3v0N0uS9CNhnO0oMkEEZS+adYaYQ6JQfQirLWr
wDbN92LnZF+50oydPESH8KA94Nl9SDm.txaRnlXbpABvwPxmP9DOlXhM8wza
N1Mw7ozX33xoEmDwDS7oMljwDShOPL4e3mW7+4M5DNA
-----------end_max5_patcher-----------
</code></pre>

Once the cubes are drawn once, we can leave them; the renderer will happily render them each frame.

Now we need to calculate the distance from each cube to its EN. To do this, we use the 3d equivalent of Pythagorean theorem (a2 + b2 = c2), which is:

x2 + y2 + z2 = d2

where x, y, and z here refer to the distance between the cube and its EN, and d is the resultant distance. So if we think of the cube as being at x1, y1, zand its EN as being at x2, y2, z2

then we can more accurately use the formula:

To carry this out, we’ll take the result of the vector subtraction we used earlier in creating the “normalized vectors” and feed it into:

expr sqrt(($f1*$f1) + ($f2*$f2) + ($f3*$f3))

And store the results in a new coll called “dist2enemy”

Show Max Compressed Code

<pre><code>
----------begin_max5_patcher----------
1487.3oc6assbaaCD8Y4uBLZxCIsJdv8K8w1OiLc7PIA4vFJRWQHWmjo+6EX
AYLsMoLrTHq8LJdjDHH.1cOKvdVPh78KlMeY0c154neC8IzrYe+hYyfpBULq
45Yy2lc2phrZnYyWUscqszMeQ7dN6cNn9ZW0NKZcdsKqbksFkWhxPk1+A4xV
VXaad9ZnwUK+qOxZqaSUoqLaqEtyeTseWtcG52qJV21fx8ayKKrNPAHc5Uc9
2fdQzWhuusU6csMts1a1Yq8JclKup7pc1UtnEywgNhzbxkhEHbnr+Kze11qL
2pOmWdcmdPk7PqTBdnGLtHbEkG5TnO+6EWD9ZQhXoGd7HwSfxatEsZ+tcdE9
J+sCx9onGcTPuUUEU6hVJ9RshKHADgJvFcnfhnjb0BDoCH8P.mbX.Wpo.foj
8B3wAx80arwlOe9g7EdsBFLIKLXDCeT7EYq9BJGsoGW.AqNNm.8kLElbTXSD
mUT.ZnzQAZbnk8hKZyDrxlNDrrLq754KPy2TTk4R.ijB7HhQorTlfkutWLeL
S8j5wbUo2zJ.tFpszt8q8MITOASB4CBPK57Ig0oBf.hnX2CV26DKtZclKqAj
ZPovM1W55vwMadaq9DJB0AXNNH0Y2ZW2LA7pLmaW9x8tHse2gztcoEPPRS2O
BGleYmGi5wgvwI6P7CX9V+fDzDOtLZgJhgHVzDy3ftIBLml.zVjSj0enLnZy
cB4pPCMsVPmxrl5I+GlLhDJH+GBaLVcau6lcn5+dm68u+caH+h+yGP+JxWl5
KSaJy7kYe3C8fQpij+gMAzxPJOBgIfdbsbbnkKB+0WF2SQJ2rmMl3AyuFqBX
Rah4mF.4Cx4pJ6iwkeP6LQO8yF0PPgn6bvVDj1uOJaYqstN6Z6S71E1xqcet
Oaj9pM4TgAvBBUFI+.mLcDxP3lpbuQzaJWuIxNnEnD.PQ3ziH8.8SSO.ttsk
967E6W6XbgZtMqXusM0QLVIUPtiXtxPgjGYLkTaBkjDXmbLC7iV2j6QqKrWI
Q6UReDeIgyDJP.RJgZngRBAVPAQILJPHBFE9UoThTDGaHwIDZiTBhSIwLYG6
QxixPKh+J7Wmhr3CIKIiIX9gxWjZjZBGJJwBkAjKQGsoFaSJRRbhgDGU5+Wi
3TZINZaRtQBfpe2.PE3nzXzzrN7PhSIzTSzj3DktwPCfHEjrgzUbAGXJhSNH
XxIRLGfM+7DPVLuMxfQmiiOaAcTXbcRxRMnrvLVz2foZlLhWLplRh9qXE73T
Sr4ASI+eLQbernk1c8kEvHscyDS5NuLsTt4MOpHF7i.OFoJ8sBTcQtOiaVuI
ILELnzCRRbX.BHGXxFxA8nsQ6goQouM3QoBXeJ9Esm4QOyidlG8LO5XGXjXd
SDXTRiwEUmiKdNt343hmiKdxwE2WFdio8FRT+JXaGgeNT.QhABE5CMz4QSMF
4TuwazkqG5w7Svz2D7GDS7IzJgsmQzO88W8RmQhmXlZo7MAP2raXFFelo9LS
8Yl5yL0+DhK5iK3CwgQp9hKdjafQ7SItXCac6mmi0tI5HwHhuWIyXPaeK7Zo
e2FxGe2FZuOuvWuGGLkI9hHi3S7UQdz3yMYk19d8xjWvKU8PGwfH2FPzohYT
HvxGoqfwNuHu7wGdUX.C0+PCn16DV0BU+HcTD4Gf1ZasKuDNuhcaU3Abhtmj
8y4q84r00.1lutI2hNm7lm.nopUvylui75WqnSpNAyqeVcJbnKlPk5Qhqech
OsNOcJ5D4Qd3Q26gSw6ENsbSpRISBpTSpV8noKCfTloeNEIIfhLcQoXonT7W
n2iFeGebQ7n+ngiHU3hSN9EMA+JXSu.skafiMLq47sFOYfvUmr5lf1JMSLEP
JKWmXZIZRgPl33Zo563SlNISgUhM4rRI48HSLszij2PZ0zt3SlDWImN8J0yy
K8BUJAiBgQY.E.mA6Z4gWQYwGPKV.+u1Hb0I60SJuM9DywlTJRxSYYq+h+8h
+CX+n8SM
-----------end_max5_patcher-----------
</code></pre>

Lastly we need to dynamically add the text next to each cube, indicating the distance from that cube to its EN.

Here we need to make modifications to the rendering section of our previous patch:

Our metro needs to be replaced with a qmetro because we will be drawing the text in between the erasure and re-rendering of the GL context. Because we must execute all eight draw events between the erase and the render, Max needs to know to wait for these events before pushing ahead, which is the purpose of qmetro. You can think of it as a variable-speed metro that slows down to make sure that every event in its path takes place before it sends another “bang.”

We’ll add this send betw_e_b so we can get a “bang” in the moment right after the context is erased and right before it is re-rendered.

In this patch we use that bang to dump the dist2enemy table, using the index to set the y location of the text (assuring that the correct value will appear next to each cube), and drawing the text using a jit.gl.text2d object with @automatic set to 0 (so multiple drawing between renders in enabled):

Show Max Compressed Code

<pre><code>
----------begin_max5_patcher----------
1118.3oc0YtsaaiCDF9Z6mhAF8pEIFhTGnbupGPuceAJVXPKRmvtRjFhT0Is
nu6KOXUaGK6nlXq3EHQJhhjZ32L7mCY943QSVndfqm.uG9JLZzOGOZjuHWAi
177nIUzGJJoZe0lTnpp3RyjaBuyvev3KulWvEemCl64vBp7NXA2rlyk.ulp4
.UxfZtjwqaaof4amZw2tEE2V3RkzHoUb+q9rpoVvqgOoJYsUP1TIjkbi2XP6
zJs3G9VgxmFsstpFSakaKcUMWaG.TiPImasZSXzGihsMDRItqQat.+Sainlh
6Ex6NVCRR8OfSbsw0jeMdr6xM8jpR9ZKHNDpdJNmOeQWTC+xnVzooVgpTUGF
hQSyIIoHGJvoQyxc+AAQxRH2.ncny9ft0qDJx73Jdn2lL4T3DkmuEmHzrWEN
OVPp4dgFr+3BRwLvUNXQo0HlBef1XTU1vhBHBnkkp0ZnpozHVUx80z1Lk0e.
rZ5Z4z19tTH4EpFo+CD2gWB81Gamlh8rEkz2f68aQLJycKK5L6Nbjz6KrilE
VXP0dP2IZwcf1nq.zR7Arww48FsDeUiCDFkEzOvmYzVTyoFN7HrRoENaFVpp
CA7NpKbBzVcYFXeivJK+PmPO4PnO6sm4IQAw19y73YA8D+Wrk4N+v4UcotQV
3ntUm.CLdgnhVBqJoE1kX6YLc1aOdwanaTeoKhri63REPyZpV40JXBsgJK7T
9K+MXnKJ4cr5X5U.Hy8jDkj063zr.CIQAIhrKxpfVakA49rzzNM2kTswc2JU
nEcSyjgjlGxEblGHyxNGX4X4ZYmUxbNHTGi+WXpV3+jw+qJuIbxYIwoivlRE
k4BW5fL4CPjwQIi2lNEcvIddjDxUeF4R.mleHf7NHCY.hYhOIYtY6cgaEmmO
LZlOeurzKAmt0M4B2k3B4sb10Rav8oYSbHsAbFxm1vqCNUbsldG+vD1ba6xs
+pT61OhrlqUV1tHmTUaShv9fcLBerVXSn.0ICStZUnZmCl3AWRdP8FedCt74
TYGnQ.oK57B0uS+SnSxwniatmcJX6u8bpHJNnniuHJ5+kMTqqE5h+exbwP1o
WFgpUzh+EVBK6BOW8IBDGM6LrT2wTo98tIuMZZNFdG1l0VXWkuypXcjTDhiu
5gVHkx3vVyO+ZSkk9ssf4Rd0icQngH+5ipOsq3TuTlBaOAQ14LO2d3gkyYTC
cCk1foQS98dd2XailzVquBAV63bnSzzuyYyCmK2bpwTKVzXBmR8tcIuZA2iP
zlle97XeSXldW4T2yXFrVUWx167A6xENDIBiOoK7ztNR3.8RO0Vn78f+LJdx
+S.eO5JeeVpsithVan8LogsgCLt1Hj98EuSkH6Um6ELFWt6F.qDrUJ6pj5cC
ONvw1WSJuGVjK6oAzjdxmqaaJNePsImH80lMQ5iqCOrXpOA3OgkW7vodYSCa
Ht+ygdNahL71zywogMbpWdtANBuWy5FVOWBoubB8BsI6C+Z7+AL2mSwF
-----------end_max5_patcher-----------
</code></pre>

 

Best Frenemy – Merry-go-round

I just discovered a set of starting positions and friend-enemy relationships that produce the BFs chasing each other in a circle while remaining opposite their ENs. These will be nice to come back to when we have a complete patch:

Relationships:

0, 1 3;
1, 3 4;
2, 3 1;
3, 4 6;
4, 2 0;
5, 4 2;
6, 0 5;
7, 6 1;

Starting Points:

0, 0.605 0.58 -0.86 0.58 0.755 0.0475;
1, -0.83 0.43 -0.93 0.84 0.0175 0.1325;
2, 0.56 0.69 0.94 0.155 0.105 0.0725;
3, -0.815 -0.04 0.995 0.045 0.095 0.7825;
4, 0.27 -0.645 0.35 0.715 0.935 0.1;
5, -0.28 -0.185 -0.755 0.4775 0.9925 0.66;
6, 0.725 0.695 0.66 0.7925 0.8175 0.575;
7, 0.125 -0.025 -0.49 0.3675 0.6125 0.455;

Best Frenemy 6 – Moving in the Right Direction – vector subtraction using vexpr

So, once we have the normalized vectors pointing us toward our cube’s BF and EN (see last post), how do we find the direction to head that is both toward our BF and away from our EN? This is actually very simple: subtract each element of the vector (list) from the corresponding element of the other vector (list).

In Max we do simple vector math using the vexpr object, with the following syntax:

$f1 refers to the float vector (list) received in the left inlet

$f2 refers to the float vector (list) received in the right inlet

So vexpr $f1-$f2 subtracts the right vector from the left vector. This can be used for any type of numeric list (rgb values, xyz coordinates, &c… The list does not have to be thought of as a spatial vector…

Here is an 2d example of vector subtraction that graphically shows the resultant vector. Note that the yellow vector is not where we intuitively might place it. It will often seem like there are more effective ways to move towards the BF (green vector) while avoiding the EN (red vector). But, mathematically, yellow shows us the “correct” way to move in order to obey the movement required by the rules of the game: move towards your BF and away from your EN. As human players, we add some assumptions to the basic rules of the game, but the computer cannot add these assumptions unless we instruct it to. So, soon, we’ll need to add some other rules to make the mathematics return a more naturalistic result.

This is visualized here in 2d to make the concept more clearly visible, but the exact same object will perform a 3d subtraction:

vexpr $f1-$f2

Things to consider:

1. Why can we use the same object to perform 2d and 3d vector math?!

2. What is the difference between “altering the vectors” and “rotating the vectors” below?

3. Can you put in your own words what each of the vectors represent? For instance:

The green vector represents the direction and distance I need to move to get to my best friend.

Do you feel like you are adequately expressing the meaning of the vectors in your own words?

 

 


Show Max Compressed Code

<pre><code>
----------begin_max5_patcher----------
2549.3oc6cs0bqZqE9YmeELLY5ra2I4ftf.Zeq8uv4sNmIC1njPKF7.3boc5
+8iPR3.1bQ1AHhT1yDyfPHsVeZsjVR5Sr+6qVYtN4UZlowOa76FqV82WsZEO
ohDVIuek4V+W2D4mwyl4ljsaow4l2HdVN80bd5Ao9uXj+D0HklsOJOL9Qimo
axSRMBiMdiFEk7xcF+2mByNjbFO6Agor6CShY24mWj51jrbi7jW7SCDY4gzP
Zbf78tw3kmBinFqoEUAOu9u3+FKSIa44lFS29lLy2UJlQgwzMI6i4xJQl3CI
w4Yg+EsHMf6cVxj2wz.lF5WHT2WHbB3g.8XYw.grKtXI+w3+Ieq38aCiin4b
TBTVT94adhImUJFD1VTLD9EKTwE..WonBC3HZx5+3VOWy2K+j84kUfUEUH1e
KWEL+sj8LjJ03WShBLKd9+b0UE+byGroMa+57T+M4b3U.rYF9rVjMrbypulZ
0aD3QWDvCwbfGRfeHfudwHuiX0Bt6nA3ddg2BC74JiQgCVlDqC3v+ioTZbYC
x.B3HgkNvw4iYoWqX5CvISHfGSegUmmf26i24u4OM6FyTU6wPWg1W7qis.BZ
Q2saV2g8p6xLHdm721QE0sYXg0j3xgJ7ovf.ZLWpGNHKJwOXKMKi0Qlgs0vB
c2B3ldfRG1V.ObyfG3hAugBxZys9MyKxqD6f4lRfOjSYsRAB5DYAZPefudgf
EzZH.qpkROfETC.q2FHGPHQzqERA81ZFXjnrdCPpp2td5P.B6SikAQ6GwhMH
wHMg4JPqF0bQfBUCIN6WL17je7ihL8pwOXvdhezdJ+88iJCnqqvJrGF31FJh
A1sR7AdjVvamO+3C1wiAio.A2yC85br5fsCC.fLRAdPB.WTm1csDq.5xGt6F
4eGpNtLRSk.jDgXEMaZWOSSyX8zVogcko+tcURdUkWo.V+ijzJlLEIEFKRBb
HoT5ygkuumHQVi0UkOrDnrNzYNAyufcqzqNqQ8wnjM+IMnhcwJy.5CpWBI6n
wMk6iGAQjyv3pi9bbs5ylOz8MaZT+4O3ug15K2Ua4JyGSCCRhKjkZEPQxk0J
y9RXWYWU744H1eWCubdRRzZ+zhVj0QzZszLuF+3vsrdXxCEhEz5v6EtcWZnn
+gCoQi8YkwSYaRShhpUThm7bCOIfYLrg9RXP9S7x5cPq1ZUT0Lqp+bszOxut
HRU+GokvWMma.KBVvgPX6vutUe6VmGDwRLdBu2NOQzrvJsFG4hSHl0qoSipU
IW8Vits7o7dEkNaiAhhAFGhgbHATHRLiRggsKnW.EOe.zZC8bzn8FQFquD3D
zMbZKllkETrRTVGO7ywvocG1mvONbxFJZMK9jYOrBEq6AvRBufdwU64Gt1k+
+lHpe5H3963gDKcpXAkr6y82F70n+zsIOSYgnyLnJ96FV.9Ot1vx.ZayFv0n
H.c1SuFXbMbL5y0ia+h.7KXBtOTG68EF04X9Tf5XwLjvPEQcz7Az4ffYa.ik
JiYIhgGZW9aanhqkZvR6KEH+wkSCunXM0EjPNLixPAPqgBQ0Z9ghjACwJhEv
1wBKsWYwH26Pr+gwmiJilypbostxZKdXz12m2bQ+8sLETt7V77lggLVuraJc
lJC2yntnGPyxCiOrZB+96ijdTFeeiIppFaCC1kvlBtT.Ur25yVtIJJ2H8RrU
EtKl9sAX9A2EyxUijat3L+LSHjYpWo8Is9MK2EyF5RjaDw8NaVUf3gh5ZAOb
2XZ3OlZDfEt.WG7poQdimFoZaTC9Ne5cAATsqS8QtKB6WIeYaMStApJ21yyH
CJB7VijajphsdMTUCi.MKjaavLUtUMBR2gr6aYhk6GpYl+yzf6YUCaVQ26mm
mFtdetXNI01rVE13wldtB64XTxZ+H4dDeHqlJsylW31cd06Xx.SasaQVCF2Q
DK2OV7qUWahuiitxYMl7rlldoDTiqzd1ePBpUoTr6FFIiDuIqrOISI9I2f3O
H9UsT5A+r+RgePxPfe0JkdvO77D+TuKMnxPAR6fB1vh4IwlmoNK1aQnsfgAV
k+1nNC5tW7SToKWWpuAUUXjFMtn80.x.ZiV2oJnUa6UUcZ8AurSKfqXKpv86
10EI3HUOULPX4dZzDvS7FggOGtfKdl95tT999+8uc8Cvau9AvONTTETrj2dx
871oKWRhiViR6jLL8dAkUurt7QHQ3VHEL9PcbRUDKpkrX.Ncx.S7HF7ltx7R
.RPDdwudWF4KUnPV3e4WZ9WdxFc25o2f2yFowye1YuC40Js92zP3EtA4UOrU
5KcAPB5RpJX.zcvnCh8wGFtXz2+CarXqQi3jPAOzZ3XpcBXBmOryoVzymMxf
DfAPRNuSBi9DeN7EZmICotwUZCLfvQ8SfSym5pgzzBKNZLRxiB6k6nPEoxRO
qw13CVuNBfExAddfEXl.VLi6H5X.XVUALhcu.lkFAX0VhiwvmChZd8NNo6b2
wju1mt9G5N9U5FpL9Qlk32CQILYcLNv.dtUvOm9Cm.Ol3GSM8ym7CiAOlsuc
8CneZSR12JV4je71hEQ4mxBiE2dI.OpGfmHFxPL8ejiauHu0WhCTTku1ECJo
0EADCEGjUabeno2WBvrzxE9tk624FxipkqXIU.hESQAKWmuDXsXEVuND7cvn
LwNfm3S8DTtxM8FQIY4XWzzQ.5RmUmXrmYvANPZnfk830OhXqwDRWU5DoWjk
SY95pWbkSUNPAzKzFppX6pWTkSUxnCzKlIBTFu0KFC6nnXqWbnGXcFhs9bRK
.pZb6nWnsx9jV5kb6dFvMb9I1b3VijaxY.2f4mXyg6YnbC6ZDGf9ZdqYxMDO
DivCVHU9DRp7hu1dl8QLI9x2ZeFbQMlRChnaRhDbzQR+E4GvR.1yBxuqNWgZ
jGShZU7UqzAzBKlb6lESkMiH.+aOwUpLQcysLDmu.g2Y8YQTLUo7U4GcOAgC
6ixWjEJesP4qEJeM0K23BysVXt0BysVXt0BysVXt0BysVXt0BysVXt0BysVX
t0BysVXt0BysVXt0BysVXt0ByslsbfZdR3rOmcr6eu6P5rcGo+py..MivEyU
9sLSoSzbk8VyTxxMOol3LkGnyTV2NWY47LkT4eJT3eg4VCEysTiDVf5DRoGB
XIYUj3qGW2DvBpc7uJZSv490xS7UaCK+evUq2uzjF2xmKObaJWTXFeYrKuJ2
Wf5eEx3UT84RKz0i8lkZ7oCQUaLp1BFnVOqmNshlccOA+GVYBMoxjWsOd8sI
SjoWl5EmrmVYBqfL40lLYMJxDlnfL4NwxjipxDXxjIWUrmHNSJNwkIXOxDX5
Eod6JPCkIhyjZNcDDnElSDUb6HdSpLczHYsr10jossCqpLAmNYRktmvSrMNQ
UYZ5vInpMcSnammBxzz1iI1U0VtKUlX27OW8+APlROGI
-----------end_max5_patcher-----------
</code></pre>

 

 

 

 

 

 

Best Frenemy 5 – Normalizing Vectors

During my son Cairo’s tutoring session I have time to pull together even one more post, and this one adds some functionality missing from the original video (and is one answer to challenge #2 from the last blog post).

This one is conceptually challenging. We’re creating here the “normalized vectors” between the objects (shown in yellow in the image). These represent the direction of each cubes BF and EN, but discard distance information. Why do we want to discard distance information? Because at any given moment each cube can only take one “step” towards its friend and away from its enemy, regardless of distance. The cubes need to know which way to go independently of how far to travel (and, in fact, they don’t really ever need to know how far to travel, although later we will make use of this information).

To get this “raw directional information,” we recall the position of the cube from the “points” table, and subtract the distance to its BF, and then to its EN. This results in the complete vectors from the cube to each related cube.

We then find the largest value within the vector and “normalize” to that value, so the vector:

[0.1] [0.2] [0.5]

becomes:

[0.2] [0.4] [1.0]

because 0.5 was the largest value int he original vector.

Since each vector now has a maximum value of 1, they are all the same size, or scale.

If we scale these down (in the patch I multiply them by 0.1), and draw them, they act as “tabs” the show the direction to the BF and the direction to EN. Placed at the object in yellow, they clarify the origin of the friend/enemy lines, especially when multiple relationships are showing.

Note that the addition of the yellow lines is not the purpose of creating the normalized vectors; in fact you’ll note it was not a feature of the patch when I made the original video. The important reason for creating these special vectors is to know which direction to “step” to approach the friend or flee the enemy. Since the length of the step will be determined by the cube itself (just as the length of our human steps is determined by us: the length of our legs and how long we choose to make our stride, and not by the physical distance of our destination), the distance to the BF and EN is irrelevant (for now) in the moment of moving, as we shall see in the next patch.

Challenges:

1. Can you change the length, thickness, and color of the “tabs”

2. Can you make the friend and enemy tabs different colors?

3. Can you make the tab stick out of the opposite side of the cube?

Enjoy!

John

 

 

Show Max Compressed Code

<pre><code>
----------begin_max5_patcher----------
3930.3oc6cs1aaibE8yN+JlJXzls0QKm2j8aososKPQZQS.JJZJLnkFYwFJR
URJ6nsn+26cl6PaIuhhTVRbY557vR7gl4xybmy8wbG4+yqtXzM4ewTNh7qI+
CxEW7ed0EW3Nk8DW3O9hQKh+xjz3R2sMZR9hElrpQWgWqx7kJ24mVDeeFoZt
gbmYRUdQIIIir1jlleOoJGNXZxj3Ji6NxKRtEtZ9L2Q+le+29t2SRSxfKfsP
Y7BCIMdsofDW5Ni8pt2snzjdG71WWlaOLofTUDmUtLtvjMIwX60JSQ7jpuoV
BsezI4qxbhI2exkElR3oHtJIO65BPfQHHTxGGbEgJjZ6qA9eP9m9OV1pEIYo
lJGTPe7j4qppOaPcODWMYdR1sM25xHg8E0lcPxTGXley+5M5v5mfY4YUY.j3
tzuMeUQB.L+l7zoadCkIeu6FngiCrm8+9pWY+wUG4vZ7zoaMnVkiiG4SbXW8
X3jU2XFserUED4d54Z0Y.aeRqGxk1WXhFvV8P.aAbBZ3sfWTqdM49jzThcJk
cBvmFUEeS4mFQlUju3A3trM7lJPDwJ0md7d6VuM7VMDv6oF3AyPxxKVDmBcw
TOr+bXJnAQNDkyNGn6SZcpLXuLEx9DcyL2Cc5O.bsTCWC5oWW9YC77zhxYDy
8DInzy.5EE3PMtBUQ078pZJ5L3MIOETVbcAHrBcfLxJ1Q.oCSt46nazUm.De
gorL9Vyt3OLOnkuEjw1IjQaGx3nIIbxLa2HF+ACSXaWsdoAakQi15w9GIMwJ
Rp8usnARYJj.i+rm.y22DXbhKm4TvCU6UEj2Lfdk++CAf8NyWVVPtbF8Wc4L
VKvqPH81iiZGdOX00mz5TIcu3KaXqvh35a.f8WNl1JtR2Tw54n1tWbcqVuMb
kNPv0aVUUkmM5j.AbgFezc7gA0+bWO+plIBuIN6V.CNklWcr8WOONaZ5i99c
bFJ8Oq9vR1ucRkbvamrI+9xx8wcBAyjTG0RL3VsCRA+p8FXqCt4ekTM91zwH
TSdC3vXEb93Jx57Uj4w2YarBig3GKtBcIGNZBD+IFPzBxsf9.f1DXj3M4ydS
45rIDHHUBLuFTTH2lmOcL4sPzUw3HKAUhsxfIdx7e1NcJUrexAI5tX34H.Ke
aKbJIJkq00gMnqHF.NjVzgYLAOS1gPVWlwvOEziCZmNaPOjKPeqDzyfs+5Fm
wa2UU0PwxeSTSUySJIv+hIfVLIIqrxxhXIQ7jPXzTWYSLv7356Cv7oeKfHIF
fKxJ5jWCJ4DmpxyJuWLs.iXRdFXN1tw8CeMEKqhNHnN1YrrGG0AShv.m1AtC
w+WxcL0rrZ90lr3a.6pWROMgtRU5M3Cpw0FHDj7gcn.o4wSc9NdR7kkgloYX
t5hz6SiSJZyY1A.c4bC3AkitjWLcaJRxr7BmiX90b3gjlVNO+dmiX2mYJJmm
rzxt93ZNTtW9xiz+Ze3oZj4CyQZSLexgPV71FRuOu3wNsCPAaOQVhPPDFPIc
u4CQp1e9PFJSTszbD5oYpJFoM9SJMZu1FFHTXyRygGu893WUjTNIN00Kf0lC
UoAgiPWfGnSDMhIxFAEPLiqr5M8OMVi9PGOMYU4IyBnWqwa.LPsOCfB0v1.3
1wdeJIf7TwnZz9mgI0CHBnN4LE8JB7R1zMNNM4141LPTeJ34sbQdN7YJmC5e
fEQ5NM8wNI5j0td388OBSdPCl9nL1v2srSIaORo4MC1BcuL5qG99NOazC.Xg
PnC2aZTBp6RnCSV.RfyXRvWQ7814WWeexzp4mLNeO.Fw2LO8Mv4Ozmc8jEr6
3V4Mt1gEpHU6K7FensvaMo.capKTdHNc6+Br+7JeAR4X5gvXL2ZiXBzuHWxH
WxIWJHWJIWpZ5xZxkgjKiNml.D3ZfJTzwxGJ2olrADMvURWFO4yjYO8u6TmM
5fQJ+ZQK3rMLZ1nVavWCKm4SVl3iTURhIbm6S799WWRV3Wgq26QloGY3Arvs
L8vFfJ6P9WO7zP6oijLcWJKnuZWsyON2P9znePQtYSEVUNYFH+YSI1kKvjYV
r9mQ964qHShsEdaR1m8KeYog3Vrg6iW6NS7mswK7oQ4YFRYkYoqstOtXZocM
QKpa06mm.AZrq6N11RtxWzc+ttdLwJp+.A0leOad7llXG6dnFSiq1nEG+oQO
mk4PgEGZDxlblpHRFisQEQ1T19XCiJhL4tjoXgUCCd4o0EhJ4l0tyAMh0ia2
JbWXfSVXltZhcz0UDvwE2ZJqH2Emtxs34VuRrZVwoojb6GAujqpgWVjuLuvN
fDmVe5aLU2aLYVGZreL53myfp08BKdKNGkRnhiNXSw7WJwk+swAU4PXPcVR1
zxMG9P3tsBKB8aVGcVpVXgGFC7yM1aDeLwP.F+tLRVb0pBPcMEhjbE3W9Uj6
Mth3vsmCRiqPdNAYgox7XwwahKqfmtmbVfnqZNN+fhWhLO414NpzeMzJVyC3
mLXrr9tCFyjjUKafti0xxviAVqhNGzcRrljiv3rnAAtIHhlBAkODFRAKS9BA
5lx7zUUFO0keSL349d8B31JIYlaA.8NSMY0x7xD6weSKSjjXoioOOFYBQmWB
jptLQJXHf5+Myu.rGTZrlXVCyk.M+qrU6jCyAyB2VDu.PayT2TkOmY2vPOX+
GqHpG2lPe26+cu6u7N3Gu+ij+7umP9ce2G93ae+u8cVmIRrEI2+dkcW.Movf
yNi2kuPvbt2.WwOdCdsLYNYB..wIYkj7rz0O57AL6OIalsArGcEbgxIfeO1l
FdKVsFabCiIevJsfjTtoyKvyocrjjlm+YvuJ7Q+Kq+9GaiGdHcDDu68WQdjF
u1NK.vKAOffv38M5Ce5WaRblacM6Uj0WQfmqu+abskaAXvFxqI61jIfP7w+3
6H+o29W+Cu6Ce7Abj7cef71+ze6s+8OX8WcmrN51z+c9AIUmEVGLM9gncXsN
vG0SC4UNZHn+ig64V05OMxqyYOkorzpRAJinFn6NlAimqq86tLdcsuVf5EdG
KWll.Jx1xD7NSwZhI0rXCUhTPkXL48XEOBiwXmupzqA31YcY43fl0G+jYiGO
FtRF7hIsz.u.V4bqyNDepWlrYT0tc9bcfYl88vXEZKChweG2UgcwGF+bTeT9
kJPeVbmCS3rxmJJLDvlUeFD6.usXSR1XXDF8.2Qfg1oVT2tYwpUVPpxBCxIY
q4gRjw895hVE2FlqpVBmbZxrYv3cVU55cOhE1xllDmvyBNK6kGLCtRz8BZn3
g8C0NGwFD6qOfvcxJqctcDb6O2MPcFq4DsfgEaRPG14XzdMJzSYY5qP8BNW8
XcSHoM7TJNC0oeiq0iI61p4mlzdpknS03DL8dK0U5.O+4SxAm.Wlm.seaNPu
UUv7b3SDsCoBjHAmrzj+yzf1WeniaMhdLGhoWOMtJ1iqdf0dgs4fuXT8c8Ob
22C2IbkOaVuAjXOCF2ecpICzJM8JLIkQrP663bsJzktRE0kqRdj6kvPbNwE0
C76rmX6rmdSvXpfK0tNPwnrHlKjVfBm45JYj10IRNleTsVK6R2wap6jxvHkx
0cZU.WswyiRf8QnDeUBG2k9RzTeo3bIGZJ3srHEX5y8VUfTG45WZH9L4e1Tx
N0cxl5NlB9iu6zgp.7YSIhTNPUKvdI.6MNqaOcAM0cZYHKBejDTcn+A0BhLE
lJ6M6N6.XW5NUifofpBDNXCzSb8EGdF4tVWD3dIHD6LQXm5Kci8U.miiMArP
tBwKNKjQwwK7DBT0LHZKUR+agtEmtVFemY50.CAPqbcbUUQBXZC+ZzXyIulE
2XbjIT+G+DZlwpqGonBqPqj7HVSYOskbDwh76jG8YXqZv70+JiiuJB12J.OT
JM6lgbMLemorJiZIUIdlIrVQ4HjqNG6LVUMj62kLn+QMrQsXekrRxea6a3XE
FgfVHOGnpDQUZHuCKuJ8qPT8Hmn601nZcGvGtVMvmpaKSF5Ir9b8nCt0m76C
iF+1U3qB0m3aJeMnB8MmppeWtYZsop85VNObfyaUutaAiO.EHVGTfB3cnfQ4
gh1KF9DqopgDYzaNYjQBzqCsVzEtnP4Oo3hXgAatf1svEok+ziKp1o0.LSAs
wEo+IFWzCJP3R42FWjROD4hVAQlUbZpjcEZTWhegVgoas4J2rYGerfvOJEsd
C5MeeJoLMYhgvOM5MJjvQ42EzA6cynBgYM72Bf6HilGWtIETb0o7V6aI2jrW
RN4KIm7kjS9RxI+wK4j8Ewne+Qn7QI1BwHM5EhwWHFegX7EhwgFw3pL6tH6z
D2AGK6cIFNlVteJwv1h6XnjOHmsCb6j31jHmFCHbb2nK8aAnP99W0eVOY.4P
0HCF9lpqCGNLrClpUpWrT+hk5WrT+hk5gWHLqr+dDgDPz6jWT9L4EE9EPls2
rlphZybc8+++3kwgg6YLstSK4t3buklcMxH7aLts90kiSzsmeaTqDZ9I0hP8
Wa9jGE9olxpjLWULrwMY+sQvF2z7jofaPaVwuKRl5MW69PMT5pcUlrKdQqxj
86a.hp+jIdWkoC.mnTs86fBJGcWlwkOd3oPdosHurvCTd80.K2+UAA9UnAd3
oPdYsoGxNP4MT3EPmbKjab3QJu7tnO7DklVkW6.OHfZb+y40NbGcJj11PW2h
NeHhqPfBHXDQZMhD9vQmBwsMkWG45AIt9BVGs4Y+x6vKtGK55VWn1IGNPkAE
pspvubQ7pFtiN1oZztn5x1ZH3bSuxB6J8Ju2jomvluaYJh0qlF6zPGsWEIWc
y0pPwNvIqr5MQoc0GOVkKcWDvvdUg298mWqxjJnWGIUcYRnR1uxTWryp52Ig
ptP2KOPEdtDc9C+9nWF9vAGKiAqSRqpWQvntHS5dUjD7gGLo5hEHV+p7K4mA
kep14BI0+qfzvGN3XGT6hrdn9k4bDymwDTtsGbrvZWDUZOOV2EYRzu1Cj5g2
zzm.AMfS8rLoNCSSOV+vFfVhbkBZ6Qdn6WsbWwx2tTE1ud5S6hPohFdxDsmC
RqK54z902dZPWG6D8m6MQcJne0.LbV9gErHSfN2yntjNIBhd7vdHi.GXtbDp
Pu34xumLT93gGMwVWrU1yIvHj1QYh1iZgxNYVR0qR0SS459jp9jZqS7szv9U
pngcRph9QPpZM05rdNwScgx8oYYuWDpVQpfCTnr+F.vlGeesCiacxsORxveq
TobFIbGczi5QcBf08KGWPWF1U8LYRGo3X8rSIcZElT5d1vYmjpPQOKUcxzYX
eGSPPmjJ4QLEDN3+9p+WKG3J0
-----------end_max5_patcher-----------
</code></pre>

Best Frenemy 4 – Drawing BF/EN Relations

Ok, I’m clearly having too much fun doing this… I also blogged it at my arts camps director’s blog last night: http://www.ballibay.com/arts-camps-directors-blog/?p=39

We have reached the exciting point of visualizing the BF/EN relationships. This requires relating the “points” table, which holds the xyz and rgb of each cube, and the “friendenemy” table, which holds the relationships between each cube and the others.

Just to step out of this particular example for a minute, it is worth noting that this technique of using one table to store relationships between elements of another table (or of multiple tables) is ubiquitous. It is called a “relational database,” and is the conceptual basis of everything from billing and invoicing software to facebook. Pretty much everything we interact with dynamically on the web is a relational database with a more or less complex structure.

In this patch we are making a new jit.gl.skecth, but it is drawing to the same OpenGL world called “world.” We’re doing this for two reasons:

1. It allows us to easily clear the lines of relation without clearing the cubes.

2. It allows us to set different lighting conditions; in this case we are disabling lighting so that the lines have a constant brightness no mater the angle from which we are viewing them.

Other than that, we are accessing the “points” table, extracting the index number and the xyz location of the cube whose BF and EN we are looking for.

We’re using the index number of the current cube to access the same index in the “friendenemy” table. In relational database lingo, this is the “key” that links the two tables.

The ”friendenemy” table in turn outputs the indexes of the friend and the enemy cube.

Again we look to the “points” table to get the xyz of the friend and the xyz of the enemy.

We combine these into lists consisting of:

Cube’s [x] [y] [z], BF’s [x] [y] [z]

and

Cube’s [x] [y] [z] EN’s [x] [y] [z]

And draw a linesegment in red or green from the current cube to its BF and EN.

We draw this on layer 1 of the GL World (whereas the cubes are on layer 0) — this doesn’t really matter here, we just need to make sure our lines and cubes are all drawn on lower layers than our eventual “bounding cube” which will be drawn on layer 2.

The lines are drawn semi-transparent just for aesthetic purposes.

Some things to play with:

1. Can you modify the patch to see multiple relationships at the same time? All friend relations, or all enemy, or everything at once?

2. Difficult: Can you think of a way to make the direction of the relationship apparent when there are multiple relations showing?

You can see it all in action by keeping the this and all the relevant previous patches open at the same time; they should all work together.

As always, Max compressed code is below.

Enjoy!

john

 

Show Max Compressed Code

<pre><code>
----------begin_max5_patcher----------
2847.3oc6b08bahjD+Ym+JlSkq6ipbzw7IPdLWsac2K6S2aatxEBFKQLBzIP
Q1Yq8+8altAaorBXrsfPpS6VQBPHld908z8ut6Q92d2UyVT7ftbF4Cjekb0U
+16t5J3R1KbU84WMaczCwYQkvsMKtX8Zcd0ravOqR+PU80yJ1llujDkkQJ04
Ikjn7DxVcbp9K5RRwcjpUZRYzZMI29xJc1lRxcolax7AqIE4vMrIZodN4ep2
psm9HIxbvlz76m2LhYo453hc4vvFTew7cqSyyzUfLRe9hE6pZtpW8U2DUEux
Hn2ZDsJblS8jr4d2PDgA12nJN7lzatG4+T+0RSfoYwhO+dQPirbWQdkcx.ez
+nX21T8VxGKxRN7FJS+JbCTyC2d0e+cuy9xMNB3458lA8Of2kjphasXwsk2q
MynlaXyVsA8qhpRKxObJxD14DyGlZd0u7zr6sgeHrwYJ.1BfgvNdmD7DNCdf
IUs3iBLm6yjR6QJZnxK3F6G7znLbf81V.6ifMuSBazNL6DR6zJTJbA23MCJ9
vqdbiFeLylcDB7CBjV5Bj9JVIK.aQgJzELkMksEayS65n60DFoL8g2qyz1ag
jkVVURhKxKMGXcBWb2GHw6Vn+KkjGd7qjO9y0G7m+T9It7IcsJ51ghzG.Zkj
N.NTjn+XE5XgwAkoc.OkVjGNltiaSqDEGqKKgPXVnMtnXaxSQ893OCAC+oe4
F38M6prWtTShfCHlvkM2pUUdR8gpa8g.8hHBFBG7BTCH4fZg5COdJskkU7fo
fBwxAAPzZCdCQC8CFmN0Jj+9O8KFxIY.LZTaQKxz1OzfGVsSpY4jQogeGT0g
mbRUiraUCmqv3irAP0v4vCjGfw2YvJlPUKZF+IglIKMVar2uyv9aaYEgS9RT
1NsUEAl+enYwAxA740So4QUOSkzpWI6WUTdv5Kxd7qkUTbu0O3cEaImTk42s
JyO.M3CFBuaA3pIEGB+SqIcZWacRclZJnyheL1t.Y01hcKWAb72TjZFsSBtr
tA2.OX8fP5MDfqDd3ROjTkOn.Esgsxo.1p2FYs1MXpEEK6gIeXnOrf22e.PO
Jkh7m3HtIXcwehymBvWx1n80NzA7y5FoT+e2oyi08fk9g.9wBTCgkn.8Liu0
GTxlDPo9tncYUXTxz36O1f7krFm4yPNaCgCTFxtOPh4oi9QacMNcBYjB.ZOF
kBEFWvqE9B2sc4B7NMWU36ICug7LJSOm9BnnfHnngrrSKXOmwYKpbPBU8MMF
RpH6SMyavde21bfSRsRprWsDHmg7gHHlT.NjBQx78.7rvIiAdsK3dgNXZEnn
8XeezmeVMs8T..GfIwx4cCvAuVK6Nl.iqQcSrwySUVjHAt.puKn2jf+pIblg
XPIIhjq2S9bZ07kYywJOYQl60IMoFBUndYFYew1rDRrgVl4y9zL3z4eZF4ea
eR0eyXi.GkZxe7y6JwL4aRoDgaLc+UQklSWtBpLSRZoMWyDxesrnNgeKmEaR
KQY6idrjn+hNO6Qxhs1uxea9qKiSzdySNDjD4XsjoTOHLrvW0UNmzQsZ.q0k
kQK0+wJ3ZvopSZ8ydwkssoFiHHiQqYsv9fJOGks8L.LK1UUUj+BV+2ABTypi
yCvTsZd8j.P60sdQT9RCHbF0xY57kUqNOp4.J+.sremZ4fIhRtkZsahH8s4q
2Vxkdnl0vdW957aH5GQMwdMObZ2ID0w5laN3eud384B6mcaRTUTMrViq1O33
dLd0rl65Wg66o6z7I2qe7.DwdEnhVOQu0yW4SuAI5FxBpaefJHDae..07P3s
f.bEwUM58SNRrSNRu2aNUvk9v.nXTVHydjT5IYvPIC8gAQxYv6999RWFNdaC
mTFDpTvv4q73pClOJANFAR7co4bWFKQaikxPzfadTlCYgp.p.NTYhwEBiKM.
mS0yMkzogS11vwTl+qd37CTd3bSIBU.n5KvQwCGMNysYmWaCmuLfEhSIA0On
dhZAQFLxgzCGNqBzkgS0JXJnJOA.aF6DXr3l4HGd5BObwe.NXh.mFK+VGKOS
jB7IxB3JDu3r.FE0W3EDnooW3Qlj0GZFVb4ZYzWzI2ZbPX7pbaTU01TSfMbG
Lb3hW85EZvWBs9qeFoRlWTYqDZTksXyIEDy4DcNz.gmX4Yq6LVDafd2epyRn
71XiopCMg0CrtLSsULDFeJPFKQuoZ0s0X10zyDsLrHdTJ14WbiNzJsroc.6r
hnDfczYgtVcWTwJ6hUOt0j05ir1jHUNcSBbqLoWkAkNuXeYcmT+R51hbnq30
8IhmPP+E1sb.YgIGsBCuGSFX1by9ZQwZygKdjDmkFe+6S1FsbIrMlrsjcikd
z6+lOIE2nRVQXeZdRw9Nae9arRmgXs.wl6Jq4h1RivoShBAkkdus+anA7MvQ
V+.06Irzbiqw0XJx6Woa1yW1joMoUWrQmqSlS9W1qaNONpTayg170pzK0amO
f9QogXWZwrYPuHs4Fk5OA1AXGWDCn9Du.+ErN3oW6HkV62P0kGC+t4oOU7lB
lfzyT5uXCc7OHbSq6vnIRbl6xJLSuNm9FpTkwQYvnXna9RMZPPA2EB9hNwj1
SsyHlQUV6lwOZSqENJJIcW4YikRyVmAIof0QsMRJB0zlkxwAgOiNfpAILnGq
6UXrojCHmH7Zx5w7VdxAm2j2PykLy2x0EEluS4Ji8mgzA08HerWI+PrWHRrq
Lh1JmGiMQLJ2DkqyNO8yfibhgIdHtCpXsVOS1rAHxj37DYhhsLNf64PrIl7G
mfSN65nAAv88CZR2J.7DpaFwz0FQ.B848CTzIXCTuOMoZ04KOZDAC8P9M396
ssPTSFuAsr.6qYDb2FxeAfCqq7wn39BzoEXdSetwma.hh9RkAAN.PT0DBfVh
sMmcdvAAVmkv5MXPHtAfaAF50N46+zQJwN9S6e5DN.yFiftPu8bwtT0rY1kM
cur8PDsmAWZ92ofAsrTdST78j6d9+OIZodogC339o0mhMsq6ePMLd3zNdvvf
Qz5efJtgQBu++JloOxjPwQzomXl7e.BZdh9o+15LdCsBSVW82YbFmeo23W5M
9kdieo23e25M9X4XrIcBdfSNFEWbLdww3EGiWbLN0bLtK2l4wYpDm31tUPAx
h9cu464x9xe091jgT8clALOQmqW+34J.BV.F+.mReUMRAPdoVjdS+P09dRr+
QbmBU6eIT8kP0WBUeIT8zKGFieAiuEOh+IcLJe4NF43OPFzwHqm5eEzW.6l+
M5AtaqIjKyfexiFkKgN29pYE0MjrnGMh.r4Fx0k5kvVx7ZJ4ZF4ZN4ZA4ZI4
Z0.tsFpaAC0iCDkTX7oV2XC7oRYY6Clav3oBLiaSm.kuCnb3P2uX3gLC+std
zeUCAIG9wIeDxWZd7wMhvSavExyBeh19WTKXCqdvcYaKzA2zpzDCo0C2kIqS
SpIWAeoVZ5kqBk8O9a8JS9ipHY+gM1OLwFUYBXURn8HT.K+WhT4KkfoMUh+Q
ICr2O9LN96ImJfEAvYuU70EU92nDFbctKxDDAapITiqHIcFlDilLE3fLIG4U
qtHSrQ1UqSt+GYWsVpISLYJb5ASBkKlSirL4TTR03Zg6O8TctfRir2IWB+xX
SNXh9B41DBEQF+4HDJaN4s5wZ.VIVKcT7O9FnbCm7VUzNEsdjCB4hllM1jqC
cw7y6HF3CuP44DWqvwEpbWn3inMkKRU3TT88MR9fy2R4rPMhpOtSIe4Mx9Db
Jjz3xug5hM02xodv4K6xZuQ1gtvonLb+Q1jxoUe7wNWU2xoW7cPp5udW7uCU
gqer5sr.zbxu+t+W5eIEj
-----------end_max5_patcher-----------
</code></pre>

 

 

Best Frenemy 3 – Making Friend/Enemy Relations

In this post we’ll establish the friend/enemy relations. This is similar to creating the initial positions and colors of our cubes, as we did in the last entry, but has some special problems, and introduces the if… then… else… object.

It’s worth noting that if… then… else… is a very much not a visual programming solution; it is borrowed from coded languages, but this is worth it, as it saves a lot of visual mess and gets the job done.

We use it here to prevent:

1. Any cube randomly becoming its own best friend (BF)  or worst enemy (EN), which, while psychologically more than possible, will not work well for our purposes here.

2. Any cule becoming the BF of its EN, or vice-versa.

The syntax the object is as follows:

$i1 (after if): The left inlet (integer)
$i2: The right inlet (integer)
!= means “is not equal to”
$i1 (after then): What is passed out left outlet (integer)
out2: the right outlet (anything)

So the object translates into natural language as:

if the int in the left inlet is not equal to the int in the right inlet, then send it (the int at the left inlet) out the left outlet, but if the if the int in the left inlet is equal to the int in the right inlet, send a BANG out the right outlet.

If you’re new to this, go back and forth between the object notation and the language above.

The bang out the right outlet triggers a new random number that will hopefully not create a conflict; but if it does, still another random number will be generated so that the relations eventually written tot he table don’t have any paradoxes.

Note that the counter is places at the right so that the index of the cube is generated first, so that the output of either the random can be rejected if it is a match for the cubes index (eg. the cube is its own BF or EN).

The pink lines are added just to aid in visual decoding of the patch since they flow “up” against the top-to-bottomness of the Max patcher flow.

Challenges to you:

1. Can you replace the if… then… else… with its fully visual-programmed counterpart (using just objects like !=, select, gate, switch, &c…)

 

2. Could you automate the patch so that you didn’t have to click the button at the top for each friend/enemy relation?

 

3. Advanced: Could you make a button that created new friend relations for existing cubes while leaving the enemy relations in place? Or vice versa?

Enjoy!

John

Show Max Compressed Code
<pre><code>
----------begin_max5_patcher----------
1682.3oc6Z0raiaCD9rySAWi.zKNA7eRUf1Csm1CE8AHaPfrMcrZrkBjT1jz
E66dImQxwIwRVNwQUsX2EvRhhlyLeyvuYF57sSFMdZ1CthwjelbAYznucxnQ
vPgAFU87nwqieX1p3BXZimksdsKsb7D7cktGJgw+yzYNx8Nxx3u5HwD+ztck
qzQVkTTRxVPtvk5V+3kWrHOwkN+xKteYVg6xuj5+JKVkbKIojDmmcW5bRQFo
boijjN28.IofrHIunbBIN7pxrb+a1H8UIotY9uDnB5pAuM2U30v3xjrzqxcy
JQySIiNmNgXjzvk5OHWV8sRuacRpWiAqj8zfY2UVOJsV.wkyVljd81KNiAKt
.jAWoBWXL4VBHYNfSYS+qyXpZCXQVZYZ7ZG7peO6NO3jS9srUy2dBEI+MLAl
8bZXzuexIgOl7N8X+wiDzY.PK3dHyhS+oRxTG3AJ7J1mHedg2iLgLaYl2g4m
Zl+U43zOem9AU69AN.8Zg3CvMvgEUSQ3OBtDoavIHGBNgO+Dj6g+r6Sq8IYU
XL3.9LId8qbA4d2V1ZhGbl5xeGtBo07A3JhfMDRUD5Jns5J3CAWAfZdwciyc
aAoLOd1MAhKfnpxqTrYqhKw4evSFM04saxrbWboa9j.4kmQy6Sq3p7dp0uEW
iwvCHlPG8A3arLbwQmCW2tygMDbNqiuIjVoJlG8FXNgMChLXm8q6Dt4GEfiw
.JEgAPLNlQQxa.3nCAf6ZuUAr4qboWWtLDQ6U.e94UqHeY7sYIdI+kwjxLRg
qDlXEb5W8j02sFv3vv0aOpF+sjBlKQhYo8if62Hwjt.wCyJaMErcX3aRc4dd
iBhjLMN85hIj7jqWVdVY1YqbK17EZhifAD2Z4G.ZZzXpTvgonFLde2XoYPvd
uJwyW6CiQp3WxUbFxNj6VAn33iBHIQPhy6.Ho6SPJ0cuWluBilRjGfgKawvQ
SFiNDB44plM7MoOvkt7wac3hLNDxOdRCW2rT8Ads1UTDes6U.1oBxoLxo7ch
Z7chZrV1Sg4zMFMju0TG6rKTiqaD15WnogPojEjSSXjO8K9K7P9gT3Y2JesR
dMlSPmYWyDuarj2BaOG49DHJVUsYSforYvbxO.zpzmXwLVK1AKsU.U7C.ce.
pR.HoppHakoU.kOf.zo2UVdPoHY6MSACn7PDI74NSTHZOSA4xiWvQUsAriDy
tB6jVfs4xn11pDf0hglDh.G.adpK1m1DDoNzRFzXsR0Pjj1NDwaEhlTssXxv
AwtMbbAIg+uS7Rb3EKHvSTDikvlaZDunlgc4BG48aBrDpNteiJ+Ov9Me63Xm
JPiJGmxzqJ3zhruLqncXZO4fl7tyEUMbQ7WcyuxKSuhdUbYYdhOiC9qPLZCr
MZra8TGnd.Ni.8AC2vgid.nYKIzY3wJyUUs60Z2dl8we0+M4zPn2YD1wYSYM
9fGBur0fMsc3rkrol+vCL6XgMUGGErSznZq0OCcXykCbU3AGdbnopAG73TY3
gD13gMw5IVpfYd073x3WxKsoOA6jpQpm0Ev71LS+atw83VPRXjuFu5tJE1yf
PMZCCN2NoIhaC2I7I2rQg6zLELPDbwZwBfGU6B2oj36TRmQOmIEJCH.Mmwi3
g6TJphChREY.gnDb3pwXTcQbhlDmRYizZPbFMUn2xdd1gUteQHaRDZgPI7qn
+Vdj1xjvsZpxDAhiYQSoxjzpNYQplDGW6+Wk3LVMEMIsLRCXoQhRghRSv4cR
bzlDmQY4QnIIYFakgpk9zOfjiXaKtfeqKhS2HXJYZpDfMe3AHKg2FEvpKoni
yhBSZ6jrLMJKpPf9FJ2JzHdI3VNC8W3.RLhjF8rHwpa8h8sUKA600R.LEvI.
7h+PH.ppv3OmirvygLqlyo93kHOQVM2UTljhGy7SSBJQeqYsLYtuTusOf40I
yqXUq9sr0giU0f+VcFKeySMzHbWUWVGz1PNnCQYkBVP870PBWXhMOcDTV1dg
V4gosGAchuOcJzjeOqSh8pS79UmDcYeQupRZSWTI.mjcWoB+JipvODB1xdjX
ySuS08EaCaXuZ+BgltveDpuuOcq1tnSlgGNgTWrAlRAab6Okh0IhBdOSd8Bx
xVTp9Codg3dqod7s1jkW2Ch0W4JT3EWQifFDLLiVZ7BZqNvNx1g3njV+ec63
kpXCAIhgXja+tGm2os38acbb4+ShB6jCGa.g2ubUcSo5wTMztT.X3O9h9LNT
2Ijpey+0I2G+8T8h+guex+7UxsfM
-----------end_max5_patcher-----------
</code></pre>


 

 

 

Best Frenemy 2 – Drawing Jello Cubes in Space!

Continuing with the idea of modeling the flocking algorithm of the children’s game “Best Friend, Worst Enemy” that begin in the last post, we will create the starting points and colors for the “Jello cubes” that represent our players, store them, and draw them.

We begin by creating a list consisting of:

jello-cube id (int) so that each cube has a unique number – created by counter
x location (float) – number from -1.0 to 1.0 created by random
y location (float) - number from -1.0 to 1.0 created by random
x location (float) - number from -1.0 to 1.0 created by random
red value (float) - number from 0.0 to 1.0 created by random
green value (float) - number from 0.0 to 1.0 created by random
blue value (float) - number from 0.0 to 1.0 created by random

these lists are stored in a collective (the coll object) named “points”

here is the patch that accomplishes this (compressed text format is at the end of the post):

Building on the OpenGL framework established in the last patch (shown with a grey background below), the coll is accessed to provide drawing instructions to the jit.gl.sketch in the form:

moveto [x][y][z], layer [layer], glcolor [r][g][b][a], cube [radius]

Rather than re-rendering the world as fast as possible, as in the last example, the world is rendered after each time all the objects have been redrawn.

Questions to consider:

1. Would you know how to alter the patch so that the cubes are drawn solid, or larger?

 

2. Would you know how to alter the patch so that the range of starting positions of the cubes could be greater?

 

3. What would you need to add if you wanted the cubes to start at least a certain distance apart?

 

To create starting points and colors for the cubes:
Show Max Compressed Code

<pre><code>
----------begin_max5_patcher----------
1755.3ocyZs0bahCE9YmeEZ7C6zcFGunaHw931m1G1eAs6jQFKmPKFx.3Vmz
o+2WoivN1tvFYiAyjIfQHz4b9NW0keb2joKx2pKmh9SzmPSl7i6lLAZx1vj5
mmLcsZabppD51z370q0YUSm4dWkdaEz9i5LcgpRiJTYKyWi19xqnxJUQUR1i
nmyKSpRxyJQqJLu6d7bTUNBOe2njljoiy2jACEstwjkv.mu3K2yH654p7rpL
0ZM7pOluoHQWf9q7zk65vyE5RC+orj6gBcbkS3BChlGLCQCv1aA0WP+a8Wks
YcRVptBjQ7AzpL4UfVXo4S1227MU657tVeVUE+jQVaklDJbKDHq8a94c2YuL
6JC7EOt.EmmlWf9lJcitFxCNSDmF0UDGGDHA4FSGNH2PThkP3n5a7dAyWLsA
DS5Mh0KhtPB1WbVjC0gqrqswVSBt3FK3Xd+K3EMI3g2VAOzIw8qf+ZSBN+1J
3bIs+E7WZRvYcMpHGKNf0GlfhGSydBt11DbQus1IL9.DRLtPay9pPY5uuKG7
AE9jjUgLM5RI2DFg6bhVFHXrfALMKO7MRxjg8BvV8jF84oE5U5hOOEsVWVpd
TiVkWDaJpQg9RR07XcZ5hz73uZKtA5o8G1OL1HglAsDkuxz2xm0wIqRhsZgT
eKAhD1YmcBX3ERFvJf3TnxGFW3zPzdo.HKDerBvfXFdXF56OkD+DREafdUI.
8F+ikkOo0UnjLz+n11bMngMn.3cUAHE.nGFxFNEfT.DqVOfcOgwWp2gIphAK
9EEPZtZ4BU195wb7V0KOqcbwT3k6kzCQU1.DTF2N9PkbmAJ3aDI5kXGez3mi
Rr1eVOdCsM1E1PAKUUJjxZItTal36bzemYBWX5XrpTOChb.ux9sPXjMKzHin
sPWLCBiaaDFjBcsMWIJw7+tY3ZswoKMV8pXM5Cam8xrW+c3CscxMsrOTL6wY
K9cu8Bv23jnvr33DvNlR3cybt0rnoZUARYzZGm6rD8aNXqDs3EDzK66bg3M8
1E1oDfXq9np5sWavTcSobw23IrHENLDtFP6lGPcdwecBKP1PGF1ZPhFCPvBt
P7gbkiPD4PHWUFDxEBPGklpUjHMozXTZPjc+2LxH6FxTj+c3Y44fTr2Eo3BW
NeoCoro92y9FuDXTDWubO+gcYVl2JTtxjappQ7CeoSb7ZYYIEtRUIPLMAuSd
dsfN0SA.GfaEgRxZCeBGE3CNpNBUTe.Pcv74FGXRPk8t4SGPG4sEcBwjwsyU
znv5oect5B.wBFEFPWI.Zwlpp7rye9QQQ+uE+4szvbRAL+aml2d8Zpqu+f8y
4LBTDciihxDtsEKrdQb6C2fKEZtw4eotkxaTBM23R2Htc4oWglKN2KSNNbon
rdO0K4BxrvhFGviawP6Zhk1lwMr3Dm4TsY2XfAe3hDy6z7raCVBNSHgdiKBw
YbTezMHy4c.Rt5gYviizS8YXlKGbBFGIn5Sv4YU7WQInUu8244bguvj3hqDF
gIPE9zH2Z+iw8AHcxB+1XVpCVou1mNzkgU7qzZ6gwgGjzpi6w5kNYHL85LYH
radPLR+ManNTeBdjDW85TeROfOijPq8J9.amz6seIu6NDL.6rD68VyAV8gej
SeCmda2.Revt+k03SM.MY59cfrdqIlLcWu9Dzu88z7lupe4fc3x1BbRSccNX
dX.G1lc4Lz8Ayi3vSLLbKLT3dTJ3Nk2jcptFoAtQZXFVILJtwlBjiSfGDNBD
gIdQ.RaDHjBre.yNZvPxYvMbfiBDteTf1FEvfLfCAtm.nSjSFhHNRHY9QBVK
ZBqhvPHpzwvB.rH03jSgP8SOvaSHDTGnH.JgARvDNRPAAT5IIBaSHv.Ah.BH
fGbJkHmdW5GFIZSBpMhjNIPvbfjyJMxoGBDGIB0+zPLmSUo5a5kO31I5GTUU
EIlzstSU+gtX50KzPjBb8mePrKvAENJ.mbX7Amba6GGPqzDQIdWTo8q9O5MG
8k5xpjL37vbXuL0+gX66zSIKWpyNb2pWmrrNDnaxPDLLAHIDPQ5NxFG+D0c.
WDjPiobXnEFglZIzr+xC2W4Ize4QJ4V4Y2oXHfP2+Xm4Wgu7K2e9UXBnaweN
Twj8jEIoTJlV2TG4YlOlLQGKWuKK2UdJxCd5DFu24IrO3T3fxSXe3oSX7dGm
B7Am3CKN4COcBi267D0mPEiQdBO93oSBXLNvog1fxKOuSKQXb.UzgV+E4EWI
FiP0.mh4D50FWMrAzsGeYOBnOv5OluE+Mf7jOEPyFTVJx6Z5wCGO4cc6zgim
B8kmHCGO4Ug4Cr8jW7DcXKBlM5b6X9UyxfZNg8lmFx4uH7J2RWJix7vOu6+P
+dbgR
-----------end_max5_patcher-----------
</code></pre>

To draw the cubes:
Show Max Compressed Code

<pre><code>
----------begin_max5_patcher----------
2584.3oc6a08aiaiD+4r+UPXDfqGfiA+Tezm5t8.50CGtGVb.2CcKBnsXrUW
YICI5MaZQ+e+FNiriSV6X43HkEEa.hkDEklg+37Emg5OdyEilV8YWyH12y9E
1EW7Gu4hKvlBMbQ60WLZo8yyJrMX2FU5tsZ5uMZLcKu6ydr4oL4l1topz2j+
6tP6hjI71lKWuLurv4wWi39FqV62zprs0UV+rE4kyut1MySLWL2.uIVZb3Ex
zpvuR8DN6WaeF503uakidfQSskyGMt831tkmgrKLDtRn2kiKsKwmbzOVstN2
UydWUQ1nv8+y27lvOi6H.MqZ4RWo+KPn7aX2Uslsv9IGaVsy5cYrkU0Nlegs
jkvlsdpqYLaVQ9rOBsk2vV5ZZrycLfdLeEaVU.NfaAOe05Ruq9uA8w947kqW
RsrglE4kNpAfvpydZge3okDiLLSXLBZZAmWh36LurKfaFT.O.Tv.YJ7pqtgf
2.V6YkN.5A.cpikUausjAXMLjryJV6strwLaY1SAyT+ab9I6EvM8IfmJQjNR
EiZ.IH7mFse.WyGT.++svUxrEED1g3MJsO0AsiH8X.2Jy.RG5wsU0E.X6psM
Ak.2RD2a71ZOyN2lWN7hywwHrlpi6f3rVO3hyEUyr97pRDolUUTgh1afalEr
l.hkro2gsUj23YtBW300riTcnqfHLI6212OLBaFFplOLZikmIr+Sk2QJM2Om
FnB8r2l6W.uVXNe0BK6S1h0t.+Lwvtp0Bl8inRGL2tvVbyU9ZaYyJ3ET5Gy.
l+2bEEWUMg81hlJV4Cn0GFUXuyUCLC7dZV4lkeStKaB6+Fdu2lCRYgQwxUU0
dKnRV.1Sq2u9XbeJwHLneoDE5WxvwCBk7.hLpAUj41fBIYHCvKfoc4exQBAj
TvO+OFyx8rr0KW0z1wZvx1ppxLXXxxrd6vqDpLZTsKFQVkN5IUBkCKhFj3ce
xUCZMA+zsZeKc95pwjLeqSCFLXWs1SvZI77aP7VQ3McCn3ZPcaS..v0LKKyc
iccwA7un6SvWFivsIpE7Q+Kgft1K3K5Evu05yW.9nO2SIJS4dG8hmPal7tJ3
BRnCAAo7oBybugVF0ONdOPr2MtBl37wkND8sNYGXoSQeuW3wjLnxMKq9jCB2
6RA6RI6R0XF5YAzBXyKHmnWpYWZXWFA9+LiYa8DtW0OYuJ.pPrMNBA5VKgZ9
IK.pDCo.H5dYUUN.Hm+h.0GEchhok+IjGWNDkA27+dQpN3RtsCgg40nOQBgZ
gnvMZkMRF21xld8KX+11S3Nezc2Ni8PKXbSTmgIZdbTrXb3LcbpLIblRAxCo
gyhDFrgT7PRB6WaeKzT3dojbuT5J9DgVYhQBDAPYpLblwvMRjTlzXjHFkDOB
gFa5B4TGhbFSRZTDRt3HtJZmwC+9e5BIzGhDQJkQAuQ3TYZThPimFwMwoH4D
IzPocHEY5zHxbHxIif+ZIWbRDmFRQ5zHDKi0DU3D0TRYmHG+PjK1jHSogjVD
mzNPizRiDobpXWxEl25B4hNHXpEQbMBaf3ARKELFU3aWyoItDhX5jNQq3CRK
tRQyMbYhJhvKEr5VAMeQMnIIRd5CjDaOEHKok1.K4L6ZP0FLabs06qymt1S4
3ZWcV2xoNzJfn8weNlCwrKzu48JhVCZZJs9hiawKOD15Sj1KkYHcMb0KQjIh
iiOw7tlWv.9rWbIZXcYRg+yYwmB9XNcWlzBSSoElJS6r.zl+OHdEOnAwU3Jm
6WzyxRZJYlzhddtA+qR9qXrWaTzTnDjfR364F6U52h85awd8sXu9VrWuXlCK
prYTtGNWaghi5TUGEQ0jrioCYel.kCcMDZnxDLupJikWl6ysEgZF3gQXC6lP
N4y8SlWvnIwlImcNPN4TPBpTXxORnhvPofTefLpKUCZTHYtU9EW6JsSKbrK6
2PakbJZeEkSx1jdb5wiHkCY7HCiBnPP4GSd9Jf7AuJdjF1jE1xLPJxVTTcKU
l.W4mxqqJCO3lJKnx1nI1Vw55JOt0ABUy62qpVBmN8NZWCbUVsc97PgaB2rZ
UnRgW8n6jSEDJvB2lWlUc6vWhAEmVDRaz1J9SUhAQ5fN8Tj+wPUVIQ3w3YAS
AfExxrF.7.CjKoJvts1Z3HLTjxpUtxPEJ+4x1BAYabgptBOl2M+PUmrWMkJE
H3Jz3AiH8oLkJhGTnNTnZTnGq+OkGdPDuopHOiMu1cG66vJBi2If8H.+S+az
80MvLSvkEsxmwgZGy9w+4aeO663WIMl+9tkT98+z6dKqpNyUCOv2ydOnw7S0
gsjv6B0q9sgZWSuf2B8LT+MfT+qbu+9L67fIrjdc6cXTTAnhnbaSI7VXNzNp
IZPmxnssDYqhrdDvpaWjCJ.a2QGaKNeVdypPkVxF9cIigVrp.cLHnKNzljQL
n0pq01eyGcAqFHf0q4OLhf.Nk+GIUWyNrr88gT8i8Ae074Eaiz5EIvbCUtRI
eyumd1.0ufy43tCf8P4rdnxgzPm15RmUHQhu5mmoEdQtyNmYYk9kbwA2rtnn
YF5ZomWZ.M9opwuIUbOiDUN3KL.ikRzqKMHQSfBY2Szg7cueroWfFHrEXfbj
wuuNuYls.alOI8EwMPKpjhxMw5iCJX.VOYcjzlgcy+XyxW2z2JVDNsYI27nm
olkN5UHlh10S1+wTzBRjQHYmTwNTHEx3Wuz2HFyfCkY6bcQ97EgkUrSSMKqp
fmoYgE2RjhWg8DDsOWToTINIgxmwdBRLrIB59TLzttfe.Q+oqu4FfXB1OrcM
bh9MBXDuZSlH84ibFacMc7e4RlVDkgUgfqN6PGiFT0YL0AWSoNfOwr8ewj9M
5qM.llVlQ5yM.rAcmX3YSobszqZaJNEogvzhQhtqvQb29McYdEbn19spz+NT
2BZzt7QJ4moUJQO4WckszUL5kIEMTFZjztaJdqvx9FNIu17JM8va4Ygg1CDI
GHm0ou1rKE8JEDaJcPINT5uj6xsXOvXadzGEJRlP6ObHz.BTy1HRt4ipjcOg
xbMfKdLi46zov1iemNsHOKyUt6fZYdV6VZg16IBcXeYK3bRNQwu+RpDzeAXe
R7q3H7KZ94jXXUBwgh3vQkPc+kmICG167GEfezrvQ42yjmTlNvSg8KFSeBXX
rL.Zwzd5KlRu0Cup8yNUZPTFu5bGIwcYjnFVzMvSxivSORr3n7TvGShJrOOB
eOGDnRZY3UmqVUXoFGEGiGVXrKrjdf4otXs7QLdeySgbWbTdRNr3jtKFXdDi
227TWXIwohSQfMLCFInZWGG3kmsNYuvwuHbk3klqzbCAbz592hiImeDCcQ8v
LnXnL9qOiscQecfQIdmD+ke0gSmJKQlNDIsUGKc6UmK.J6AGCs7mLhSKVY6E
mKy1EAvgcptKFNTCqNQXC3ebdZX8qp5xBbdDi267j3qOKrcwzwi369lmh3e0
AScI.6gEjDccsxOWVBt3Oey+GkuJpt.
-----------end_max5_patcher-----------
</code></pre>

Best Frenemy 1 – Intro to OpenGL in Max/MSP

Welcome to my new visual programming blog! I’ll be working through some programs here in Max/MSP/Jitter, Quartz Composer, Impure, and maybe some other environments as well.

Today I’m starting with a rather sophisticated little patch that models the children’s game “best friend, worst enemy” in a 3-D environment.

In the Experimental Ensemble class in the M.F.A. program in performance that I direct at Brooklyn College, one of the students introduced “best friend, worst enemy” during one of our ensemble building warmups. The rules are simple:

from the group, pick a best friend
shhhh!!!
from the group, pick a worst enemy
shhhh!!!
When the game begins, get as close as possible to your best friend while staying as far as possible from your worst enemy.
go!

Much to everyone’s surprise, the game had us running in circles, smushed up against each other, forming and re-forming clusters and lines and subgroups in wonderful, ever-changing patterns. And laughing our heads off! It was a magnificent exercise, and lead to a wonderful conversation about how great complexity emerges from simple systems and rule sets.

As I teach nearly the same group in a Max/MSP class the day before, I told the group I’d take some time over the week and model the behavior in Max so that they could have a programming example that was strongly connected to their real-world experience of the game.

You can view the output of the patch here, with a narration by me explaining a bit:

Untitled from john jannone on Vimeo.

I’ll share the first step towards this patch here. You’ll need a basic knowledge of Max/MSP/Jitter (http://www.cycling74.com) to follow along.

For today, just some basic OpenGL setup for using 3d graphics in Max, resulting in some simple 3d forms, like this:

This part of the patch establishes a jit.window, and a jit.gl.render object that will render 3d imagery directly to that window. Note that they share the same name, “world.” This is essential to their connection.

In this next section, we add jit.gl.sketch, a sketch pad for 3d imagery. We send it some initial settings, and attach a jit.gl.handle that adds click-and-drag rotation and scaling to the sketch. There are several message boxes with sample drawing commands; see the documentation for many more. Note that every object drawn is retained in the jit.gl.sketch until it is “reset.” Since the reset message is included at the beginning of the lower message, that rotates the red cone, all previously added objects are erased.

Some sef-test questions you can answer in your playing with this:

1. Can you make the other objects stay on screen while the red cone is rotated? Do they rotate, too? Why? Can you stop it?

 

2. Can you make other attributes of other shapes dynamic using number boxes and $ notation?

 

3. What happens if you add another jit.gl.sketch with the same name, “world.” What happens to the object creation messages you send to this one?

 

Below is the code.

Enjoy!

John

Show Max Compressed Code

<pre><code>
----------begin_max5_patcher----------
1884.3ocyZs0iZiCE94Y9UXg1GZkxfhct2m5z9P2c09Tec0ppPhARmPbTbnT
ZU+uuGerCCLCPCj.AIfPbbhO96b724hyOu+tQSDemKGQdG4eI2c2Ou+t6vlT
Mbm476FsH96I4wRraiRDKVvKpGYouVM+60X60y4julUOdV9X4S75j4DwjuxS
pIYRRLwIknasLNcL4upIoUwqjD923Uqa53ZwRhjWjRxpsHwvwm37RI1yrhYD
X.VPVVTmki8rhK4vCudbijjmUvSDPGThiiowrTT3fQ3AG6ldNUTTWDufiW5i
hkUY7JxGD4oMcnT8vKpiqyDEeoBjMM.w7nissHTaWO0QayOj+ybaEKWjUjyq
Qfht0fIy9ANXzP3V1zWwx5lN2zZYL.Qvj8vCpmCNr933ptoec+8perZo5CF2
I7plIpVDpWWx0C1nLklkLZRbwrQalWaAhrnVChmOZvNLZPibUS+vHDLBPrf4
dlXwgLkqDfpmqLaq3ojDQAm7lrBRJeVEmKeKXblCsMZOnieWMwbX3DKzK7JZ
gE3uEl5xnWDPMkChhBTyyMK3k6CAc67hTGFNarulHnChYgNHP534eYPPjxLl
TWEWHKiqf9PVyyyEqHIKmvIwU.6Wphmj.Oq5FZU0sUrWRR1dveZWwe+PDyCB
XWO72MLROltag+tryD+Wvkx3Y7Wg+yxSD4hJBcr5is5iikF5sGyNHk5d4Qog
cEmotN54ryuGmYmBNSOB66NioiCRXvXWJ6bdbNQVNmWwI0BzttJa1758PaP8
5rYqOZ6D3Ze8La2cLuzzFSxWx0VqfuLEXl.894PA1FM6LIrOko8OGcEQylwL
.QSc3RmMZdHR.LrSKhbdbIW.vAvA+GTMYfEYg3abvR0drm4qEYKRCrSve.Ni
0.ObJ.kXSLEQxQInaGmBy67hMq2XGzwlEwPOudLT26Z2ylyfkqT4qiSlIDPt
BEY0YJdB.e.wQRlBfsNOjlvLF2ZmeNWgfaOlaLeDxLFxlH86c2Xo7x54egWD
OImC1tmleKFafswzdfb0bkTsiny1CTAeELodEBkKhSwLfNDzb3ziruBVPGAd
7vUfdAHEXTvEwexVI5OGxRGLhhUwfJQeJ7hukUIJT2HQLEaBR82rPT4EGb+n
SuJESw+GBwB3uSVSRxyRd5AvY0rYpr8UWTTpbq7vKthw6kRDVArnhU6c4s6d
bqEMrKuYd35ZSvplk2Ag8r5IO6IH9eiErE9OES.VYEI.d.+3BzcMY0btFJQY
UUmFQIufqpOipc37jXIWUJF31p4y3UslIkFLrPM0SGgputlIznNwjdHnVU.J
znuBvIh1OOXhKE4YojYU70j2THpMWQg8H.+o+A8dMEzLJOVjRAftVDnmjO9m
O9YxarAO4ducL4wboffOfO+oO7HQTAQL.2v6HeFVw7oJNn89fJltGyKmGqe.
OB8jDiC0emUuUzc6nvnz8nw7GVMlIrMpqt5C15Xgs6axKcAGo1KjV.fpfpop
TkgikBoD7HZQp3O.oVqhNSoaWIpddluCJ5sGPjNvl8gtZPDIZLmE42yXXREG
KOFBOHCrxda07LfDYCjAWIOWw1mlIKyiWyaOHZOrfnmq1uotrq9NcBCOTPX6
jovNIJfoHn+X0j86IWdggNJM7lfDaQLzSmeKicIRE6DK6xPCLZyoPckS78tH
3xFaq8XZYuwzxT2pSL9+ngE+hB2prBdZWF8cz+6tIV6v++ZLx5.3TvvtMILa
ydFoyOh1sJKUKlMKmez8LZeXf6QmhsVm6qclwLQDz7aepxWvqqDjmc7z9D9n
C65AC13G1C46clZYmdVM2CZ4CQLNcYdtLACb9Tq6gC6VPQq8mR06H7knpGXl
hmJzLrk7foK2an17Qmo2YuF.RJCF3CN+wb1d89iWWkIShywdYONZOLgdCr6f
fs1YW8lj0+EFONMao7jWX45OrKrLPiodhlzNuLQTXpV1YFQAK3lvFJRy8zw0
Ysp1zTKBbnHcqyyU6+mRtdtI4Bg.tG4bv9qX1yjWcXiTnCcUt8zoGP0uPFZi
RW692nzj8tNg82if+jkSmBSQJ48aJPE83gEcHCV2A1f027dfffWPXmrW68MJ
veXcZ5ZaBbzuGBb7PKlwxh9klTO817kN9zbQLvaqoAqX5WnHVzEI3qZxDcYj
+sq0z8Z+zVd2Bq3XZZKJkdIVxY7kZpP6w8kdT5IJ6lfehYNv1+qxHJ4nurW7
R5hOPU66BgRP5SZl+MuvljmeyKR4RfSG2+ms6j2NcZdVZJuX6xjtHKE2lBiP
b.EZakI0K+zuUlBtphzKPfaAQBiB4FSlhtAQoaNQxsERD85BRsQhtxj.NsQw
4dc0bNsQ08BA+haM42FB7qrEdaXKegfeokIuVYieh3jKDDiG3V1yWcH34S5L
q0EQb6Eoh12RkZSuPbS+BuP2bRGE21rv35xoc64K5E5paAQxoMbGWY8lcqVM
xt4voSUjbPdLWp90Dwis4rtBfrKfSpF4KzS+tbs4jWjgz8+59+GPxAwYL
-----------end_max5_patcher-----------
</code></pre>