今年もハロウィンが早くやって来ました。 去年使ったこの Raspberry Pi プロジェクト一晩のエンターテイメントを得るために。 今年はJMPとArduinoナノ. nano について詳しくは、以下をご覧ください。
一緒に遊んでたから地球の絵を球体に包み込む, 代わりにラップする同様の頭蓋骨のテクスチャを見つけられないかと思いました。 私はもっと良いものを見つけました:これサイト3Dモデルがあります。 このプロジェクトは、リンクが指すモデルを使用します。 名前を使ってくれた人に感謝印刷可能なモデル。
添付ファイルは完全な JSL です。このブログのスニペットは不完全で、完全に一致しない可能性があります。
zip ファイル内 (JMP の zip アーカイブを使用して開きます):
</CODE></DIR></PRE><P><STRONG>{"Skull_v3_L2.123c1407fc1e-ea5c-4cb9-9072-d28b8aba4c36/",</STRONG><BR /><STRONG> "スカル_v3_L2.123c1407fc1e-ea5c-4cb9-9072-d28b8aba4c36/スカル.jpg",</STRONG><BR /><STRONG> "Skull_v3_L2.123c1407fc1e-ea5c-4cb9-9072-d28b8aba4c36/12140_Skull_v3_L2.obj",</STRONG><BR /><STRONG> "Skull_v3_L2.123c1407fc1e-ea5c-4cb9-9072-d28b8aba4c36/12140_Skull_v3_L2.mtl"}</STRONG></P><P> </P><P>それは 3 つのファイルと、それらを保持するディレクトリです。 .mtl ファイルが何をするものかはわかりませんが、この投稿は主に .obj ファイルに関するものです。 .jpg は非常に興味深いもので、後で使用され、次のようになります。</P><PRE><CODE class=" language-jsl">jpgblob=za<<READ></READ>za = open("e:/Skull_v3_L2.123c1407fc1e-ea5c-4cb9-9072-d28b8aba4c36.zip",zip);
members = za<
Texture map for skull, 1/4 sizeTexture map for skull, 1/4 sizeTexture map for skull, 1/4 sizeTexture map for skull, 1/4 size頭蓋骨のテクスチャ マップ、1/4 サイズ
OBJ ファイルには残りのデータ (3D ポイントとその 2D テクスチャ マップ座標) が含まれています。 ファイル形式の説明がありますここ. ファイルには次の内容が含まれていますv- 3D 座標のセクション、 vt-テクスチャ マップ座標のセクション、ん-法線ベクトルのセクション、 f-面のセクション (3 つまたは 4 つの側面ポリゴン)、およびその他のいくつかのアイテム。
# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware
# File Created: 21.12.2011 14:29:19
mtllib 12140_Skull_v3_L2.mtl
#
# object 12140_Skull_v3_jaw
#
v -1.6458 -14.7959 1.0976
v -1.2548 -14.9644 1.0679
...
v 0.8637 -15.1231 0.7422
v 0.4355 -15.2145 0.7175
# 6114 vertices
vn -0.4113 -0.8998 0.1457
vn -0.3415 -0.9275 0.1520
...
vn 0.2578 -0.9662 0.0017
vn 0.1450 -0.9890 -0.0288
# 6114 vertex normals
vt 0.2309 0.7002 0.0000
vt 0.2363 0.7000 0.0000
...
vt 0.2632 0.6958 0.0000
vt 0.2578 0.6955 0.0000
# 6434 texture coords
g 12140_Skull_v3_jaw
usemtl 12140_Skull_v3
s 2
f 1/1/1 2/2/2 3/3/3 4/4/4
f 2/2/2 5/5/5 6/6/6 3/3/3
f 7/7/7 8/8/8 3/3/3 6/6/6
f 8/8/8 9/9/9 4/4/4 3/3/3
f 5/5/5 10/10/10 11/11/11 6/6/6
f 10/10/10 12/12/12 13/13/13 11/11/11
f 14/14/14 15/15/15 11/11/11 13/13/13
...
f 6109/6429/6109 6108/6428/6108 6113/6433/6113 6114/6434/6114
f 3086/3247/3086 3097/3258/3097 6114/6434/6114 6113/6433/6113
f 3097/3258/3097 12/12/12 3072/3233/3072 6114/6434/6114
# 6112 polygons
#
# object 12140_Skull_v3_teeth
#
...
上のファイルの非常に要約されたコピーには、# コメント、空白行、3 つの点を持つ三角形の面と多数の四角形の面、およびいくつかの g と s のレコードが含まれていますが、これらは無視します。
JSL はパターン マッチでそれらを効率的に読み取ることができます。 まず、OBJ を文字列に取得します。
obj=za<<READ></READ>
String( "# 3ds Max ... 合計文字数 6171025 ...ライゴン
" ) が割り当てられました。
次に、それを解析します。 解析されたデータ値を保持するリストをいくつか設定し、いくつかのヘルパー パターンを作成します。
vertex = {};
normal = {};
texture = {};
quad = {};
triangle = {};
seg={};
number=patspan("0123456789-.");
threenums = number>>n1+" "+number>>n2+" "+number>>n3+patspan(" \!n\!r");
integer = patspan("0123456789");
threetriples =
integer>>n1+"/"+integer>>n2+"/"+integer>>n3+patspan(" ")+
integer>>n4+"/"+integer>>n5+"/"+integer>>n6+patspan(" ")+
integer>>n7+"/"+integer>>n8+"/"+integer>>n9;
fourthtriple =
integer>>n10+"/"+integer>>n11+"/"+integer>>n12;いくつかの面は三角形であり、いくつかは四角形です。 のトリプルと4番目トリプル以下では、顔を効率的に解析して適切なリストに格納するために使用されます: 四角形または三角形。
objpat =
("f"+patspan(" ")+
// in this file, the "f" records all look like one of these:
// f 10714/11419/10714 10713/11418/10713 10658/11363/10658 <<< trailing space
// or
// f 39694/42282/39694 39692/42679/39692 40060/42677/40060 39722/42283/39722 <<< trailing space
threetriples+
(
(patspan(" ")+fourthtriple+patspan(" \!n\!r")+ //
pattest(insertinto(quad,evallist({evallist({num(n1),num(n2),num(n3),num(n4),num(n5),num(n6),num(n7),num(n8),num(n9),num(n10),num(n11),num(n12)})}));1))
| //
(patspan(" \!n\!r")+ //
pattest(insertinto(triangle,evallist({evallist({num(n1),num(n2),num(n3),num(n4),num(n5),num(n6),num(n7),num(n8),num(n9)})}));1))
)
) | // in this file, the v, vt, vn records have x,y,z values
("v"+patspan(" ")+threenums+pattest(insertinto(vertex,evallist({evallist({num(n1),num(n2),num(n3)})}));1))|
("vt"+patspan(" ")+threenums+pattest(insertinto(texture,evallist({evallist({num(n1),num(n2),num(n3)})}));1))|
("vn"+patspan(" ")+threenums+pattest(insertinto(normal,evallist({evallist({num(n1),num(n2),num(n3)})}));1))|
("g"+patspan(" ")+
patbreak("\!n\!r")>>SegName+
pattest(insertinto(seg,// 2 is quads, 3 is triangles, 1 is name (mostly unused)
evallist({evallist({segname,nitems(quad),nitems(triangle)})}));
1)+
patspan("\!n\!r")
) |
("#"+patbreak("\!n\!r")+patspan("\!n\!r")) |
(patbreak("\!n\!r")>>log("unused data")+patspan("\!n\!r"));オブジェパット上で定義した、パターンを保持します。まだ何も解析されていません。 オブジェパットOBJ ファイル内の 1 行を一致させる方法をパターン マッチャー (下記) に指示します。 以下は、パターン マッチャーの呼び出しです。パターン マッチング JSL をもう少し追加して、マッチャーがファイル内のすべてのレコードをループするようにします。
それは言う: 以前にロードされたテキストを使用するオブジェクト、左の位置 0 から開始し、繰り返し使用します観察するパターンを右の位置 0 まで動かします。 成功するたびに観察する、すでに行われた作業を隔離して、JMPが余分な記録を保持する必要がないようにします。
rc = patmatch(obj,
patpos(0)+
patrepeat(objpat+patfence())+
patrpos(0)
);
show(rc);
99(未使用データ) mtllib 12140_Skull_v3_L2.mtl
487834(未使用データ) usemtl 12140_Skull_v3
487857(未使用データ) s 2
1305132(未使用データ) usemtl 12140_Skull_v3
1305155(未使用データ) s 1
2038681(未使用データ) usemtl 12140_Skull_v3
2038704(未使用データ) s 1
4326305(未使用データ) usemtl 12140_Skull_v3
4326328(未使用データ) s 2
rc = 1;
rc==1 は良いことです。パターンは最初から最後まで一致します。 log() 関数観察する未使用データに関する行を作成しています。これらのデータ行は役に立たないようです。 そしてその過程で、マッチャーはこの JSL をそれぞれに対して実行しました。 vnレコード (および他のレコードについても同様):
pattest(insertinto(normal,evallist({evallist({num(n1),num(n2),num(n3)})}));1)JSLリストを埋めた普通すべての頂点法線で。 (法線ベクトルは、OpenGL に、光がサーフェスから跳ね返る方向を伝えます。) 末尾の ;1 は、pattest() が成功する必要があることを伝え、マッチャーは前進を続けます。
頂点リストは 3 項目のリストのリストです。項目は x、y、z 座標です。
{{-1.6458, -14.7959, 1.0976},
{-1.2548, -14.9644, 1.0679},
{-1.2202, -14.8974, 1.4306},
{-1.6069, -14.7373, 1.4505},
{-0.8477, -15.1013, 1.036},
{-0.8223, -15.0288, 1.403},
{-0.7966, -14.9354, 1.8162},
{-1.1896, -14.811, 1.8424},
{-1.5761, -14.6593, 1.8511},
{-0.4272, -15.1961, 1.01},
{-0.4138, -15.1209, 1.3778},
{-0.0001, -15.2327, 0.9984},
{-0.0001, -15.1568, 1.3658},
{0, -15.0543, 1.7793},
{-0.3993, -15.0212, 1.7914},
...Faces リストは三角形と四角形に分かれています。 トライアングル リストはリストのリストでもあります。
{{6148, 6468, 6148, 6150, 6470, 6150, 6151, 6471, 6151},
{6149, 6469, 6149, 6148, 6468, 6148, 6151, 6471, 6151},
{6174, 6494, 6174, 6175, 6495, 6175, 6151, 6471, 6151},
{6150, 6470, 6150, 6174, 6494, 6174, 6151, 6471, 6151},
{6198, 6518, 6198, 6199, 6519, 6199, 6151, 6471, 6151},
{6175, 6495, 6175, 6198, 6518, 6198, 6151, 6471, 6151}, これら 3 つのトリプルは、頂点、テクスチャ、および法線リストへのインデックスです。 テクスチャ リストは 0..1 座標を使用して、上記のテクスチャ マップから色を選択します。 JSLリストセグ4 つの項目があり、それぞれのリストにはセグメント名 (頭蓋骨、顎、上の歯、下の歯) と開始位置が含まれています。三角形とクワッドリスト。
この JSL はデータを JSL にロードしますSceneDisplayListsそれぞれのためにセグアイテム:
// load model into OpenGL
// seg describes 4 segments (jaw, top teeth, bot teeth, skull)
// for Halloween I want two segments, skull and jaw, with the
// teeth welded on already.
// so, load the segs, then recombine them...
displaylists = {};
for(iDisplayList=1,iDisplayList<=nitems(seg),iDisplayList +=1,
partial = Scene Display List();
partial << BEGIN( QUADS );
// the seg notes its startinq quad/triangle, use the next seg
// to find this segs end. or the rest, for the last seg.
// 2 is quads, 3 is triangles
lastquad = if(iDisplayList < nitems(seg),seg[iDisplayList+1][2],nitems(quad));
for(i=seg[iDisplayList][2]+1,i<=lastquad,i+=1,
for(q=0,q<12,q+=3,
partial << Normal( normal[quad[i][q+3]][1], normal[quad[i][q+3]][2], normal[quad[i][q+3]][3] );
tx=texture[quad[i][q+2]][1];
ty=texture[quad[i][q+2]][2];
c=jpg[(1-ty)*(nrows(jpg)-1)+1,(tx)*(ncols(jpg)-1)+1];
partial << Color( c );
partial << Vertex( vertex[quad[i][q+1]][1], vertex[quad[i][q+1]][2], vertex[quad[i][q+1]][3] );
);
);
partial << END;
partial << BEGIN( TRIANGLES );
lasttriangle = if(iDisplayList < nitems(seg),seg[iDisplayList+1][3],nitems(triangle));
for(i=seg[iDisplayList][3]+1,i<=lasttriangle,i+=1,
for(t=0,t<9,t+=3,
partial << Normal( normal[triangle[i][t+3]][1], normal[triangle[i][t+3]][2], normal[triangle[i][t+3]][3] );
tx=texture[quad[i][t+2]][1];
ty=texture[quad[i][t+2]][2];
c=jpg[(1-ty)*(nrows(jpg)-1)+1,(tx)*(ncols(jpg)-1)+1];
partial << Color( c );
partial << Vertex( vertex[triangle[i][t+1]][1], vertex[triangle[i][t+1]][2], vertex[triangle[i][t+1]][3] );
);
);
partial << END;
displaylists[iDisplayList] = partial;
);これは同じロジックで、2 回、1 回は三角形を作成し、もう 1 回は四角形を作成します。
JSL は 4 つの部分から 4 つの表示リストを作成しました。添付ファイルはそれらを結合してアニメーション化し、ハロウィーン風の目玉を追加します。 写真の時間...
Halloween early evening, model in windowHalloween early evening, model in windowHalloween early evening, model in windowHalloween early evening, model in windowハロウィーンの夕方、窓辺のモデル
目がカメラマンを追っているように見えますか? 窓の下の隙間は何でしょうか?
Arduino Nano および PIR センサー
目で人を追跡するには、ある種のセンサーが必要です。PIRセンサーシングルビットインターフェイス (何かが動いた!) と、応答時間にいくつかの制限があります。 ハロウィーンの投票率が低いことを考えると、彼らは正しい選択でした. Raspberry PI カメラを使用すると、パフォーマンスが向上する可能性があります。 窓の下の隙間には 5 つの PIR センサーが取り付けられます。コリメータ人々が歩く可能性のある地域を監視するためです。 セットアップは次のとおりです。
They do like like eyes. Those collimator tubes are re-purposed.They do like like eyes. Those collimator tubes are re-purposed.They do like like eyes. Those collimator tubes are re-purposed.They do like like eyes. Those collimator tubes are re-purposed.彼らは目が好きです。 これらのコリメータチューブは再利用されます。
そして、Arduino Nanoにテープで貼り付け、熱接着し、ジャンパー配線したアセンブリは次のようになります。 ナノは小さいです。
Arduino Nano on left under zip-ties. PIR sensors on right hot-glued to collimators. There are two orange adjustments on each PIR.Arduino Nano on left under zip-ties. PIR sensors on right hot-glued to collimators. There are two orange adjustments on each PIR.Arduino Nano on left under zip-ties. PIR sensors on right hot-glued to collimators. There are two orange adjustments on each PIR.Arduino Nano on left under zip-ties. PIR sensors on right hot-glued to collimators. There are two orange adjustments on each PIR.結束バンドの下の左側にあるArduino Nano。 右側の PIR センサーはコリメータに熱接着されています。 各 PIR には 2 つのオレンジ色の調整があります。
Nano クローンには、はんだ付けできるヘッダーピンが付いているか、Nano にワイヤーをはんだ付けできます。 ジャンパー線を半分に切って一方の端をはんだ付けすると、バラバラになる可能性が少し低くなり、別のプロジェクトで再利用する可能性が少し高くなります.
Nano has wires soldered on, orange is +5, green is ground, purple/gray/blue are data linesNano has wires soldered on, orange is +5, green is ground, purple/gray/blue are data linesNano has wires soldered on, orange is +5, green is ground, purple/gray/blue are data linesNano has wires soldered on, orange is +5, green is ground, purple/gray/blue are data linesNano にはワイヤがはんだ付けされています。オレンジは +5、緑はアース、紫/灰色/青はデータ ラインです。
Nano で実行されるコードは次のとおりです。 Arduino IDE を使用して、USB 接続経由でコンパイルおよびダウンロードします。 IDE を使用すると、USB ポートに割り当てられている COM ポート番号を簡単に見つけることができます。 JSL でもそれが必要になります。 添付ファイルには余分な .txt 拡張子が付いています。拡張子が .ino だけになるように名前を変更します。
Arduino IDE showing code to read sensors and send to JMPArduino IDE showing code to read sensors and send to JMPArduino IDE showing code to read sensors and send to JMPArduino IDE showing code to read sensors and send to JMPセンサーを読み取って JMP に送信するコードを示す Arduino IDE
セットアップ ルーチンは 1 回実行されます。ループ ルーチンは何度も何度も、永遠に呼び出されます。 Delay(100) は、ループが再度実行されるまで 1/10 秒待機します。 2、3、4、5、6 はセンサーに接続されているピンです。 シリアル ポートに出力されたものはすべて、DataFeed を使用して JMP で読み取ることができます。 これは、そのための JSL の別のスニペットです。言葉() 関数を使用して、データ ラインから 5 つのセンサー値を取得します。
sensorBits = [0, 0, 0, 0, 0];
feed = Open Datafeed(
Connect( Port( "com4" ), Baud rate( 115200 ), Parity( none ), DataBits( 8 ) ),
Set Script(
Local( {i, txt, temp = sensorBits},
txt = feed << getLines;
for(iline=1,iline<=nitems(txt),iline+=1,
For( i = 1, i <= N Rows( sensorBits ), i += 1,
temp[i] += Num( Word( i, txt[iline], "," ) )
);
If( Any( Is Missing( temp ) ),
Show( temp,chartoblob(txt[iline]) ),
sensorBits = temp * .9;
try(tb<<SETTEXT></SETTEXT>データフィードを正しく閉じる必要があります。そうしないと、次回もポートがまだ使用中であることがわかります。それが OnClose ロジックの動作です。 他のすべては単に維持するだけですセンサービットマトリックスは、センサー ビットがオンの場合はインクリメントし、オフの場合はフェードすることによって更新されます。 センサーは少なくとも 3 秒間オンのままで、カウントは約 10 まで上がり、すぐにほぼゼロに戻ります。
それはそれだけです。 JSL (アタッチメント) の最後近くにループがあり、センサーに反応して目とモデルを回転させます...そして、頭蓋骨が退屈になったことを検出し、アニメーションを実行して、トリック オア トリートを引き付けます。 JSL はおそらく、何も接続されていない場合でもデータフィードを使用して実行されます。 com ポートに満足していない可能性があり、2 回目に実行すると本当に満足できない可能性があります。 comポートをコメントアウトするのは簡単なはずです。
追跡眼球は機能しますが、数秒の遅れがあります。 立っている場所を知るのに役立ちます。 アニメーションにより、視聴者は自分たちが見られていることがわかりにくくなりました。
また、JMP は現在 (JMP 15) テクスチャ マッピングを実際にはサポートしていないため、少し遅いです。 古いラップトップを使用しても 15 FPS が得られましたが、これはハロウィーンには十分です。
8pm, about to rain. Candy Corn half gone, glow sticks popular, vampire teeth and bubbles too!8pm, about to rain. Candy Corn half gone, glow sticks popular, vampire teeth and bubbles too!8pm, about to rain. Candy Corn half gone, glow sticks popular, vampire teeth and bubbles too!8pm, about to rain. Candy Corn half gone, glow sticks popular, vampire teeth and bubbles too!午後8時、雨が降り出しそうです。 キャンディーコーンは半分なくなり、サイリウムは人気、吸血鬼の歯や泡も!
そして、そのプロジェクターは明るいです! こちらは、半透明のブラインドに投影する特別なプロジェクター スタンドです。
Not recommended if you have a cat.Not recommended if you have a cat.Not recommended if you have a cat.Not recommended if you have a cat.猫を飼っている場合はお勧めしません。
と、前回のハロウィン三部作の投稿。
short loop of animation possibilityshort loop of animation possibilityshort loop of animation possibilityshort loop of animation possibilityアニメーション可能性の短いループ