福野泰介の一日一創 - create every day

日々進化するテクノロジーに、教育現場はどうついていくか?

一日一創2012から、「1to20」のセルフカバー、1から20までをすばやくタッチする「one2twenty VR

one2twenty VR
1から20までの数を楽しく、体を使って覚えられる!?
VRで無限に創れる、eスポーツ!

こどもとVRの問題は懸案ながら、触れる算数、体験できる歴史や理科。VRによる学びは超強力。
テクノロジーを活かすと活かさないの差は広がるばかり。
だからこそ、その本質を伝えよう。


PFU元社長で、ITビジネスプラザ武蔵の館長、長谷川さん!
すべての大人も体験すべきな、VR。ITビジネスプラザに1つあってもいいかも!


金沢市のITビジネスプラザ武蔵のディレクターに就任した、元前原小学校、校長先生の松田さんのお祝い会@金沢!


素敵な町家。


素敵な橋。


素敵な料理(金沢好きの版画家、クリフトンカーフ氏の元お家、いち凛


金沢の素敵な坂、暗がり坂。(クリフトンカーフ氏のギャラリー近く)

地域それぞれに根付くDNAを引き継いだこどもたちの活躍の場、どんどん広げてあげましょう!


one2twenty」 (program in HTML/JavaScript WebVR with A-Frame)

links
-
VRではじめる現代HTML入門 - Oculus Quest x 福井高専生
- 50行で作るVRマイクラ風 / boxcraft for Oculus Quest with A-Frame
- モバイル時代こそバス! つつじバスロケVRビジュアライズ - リアルタイムオープンデータ x Oculus Quest
- 異次元の分かりやすさ、触って学ぶVR数学、ベジェ曲線編 on Oculus Quest

体験しないことには分からないのが、VR。
3DoFと予備、見渡すことしかできない自由度3のOculus Goや、スマホVRとは別次元の歩き回れる自由度6の6DoF対応、Oculus Questで、デザインツール試作。

大好きなベジェ曲線をVR化してみたところ、想像以上に楽しいものでした。

BezierVR for Oculus Quest

ベジェ曲線とは、視点終点に加えて制御点を2つ加えて計算してつくる曲線。イラストレーターや、スムーズに拡大縮小できるフォントなどで使われています。(2Dベジェ曲線 - 一日一創2012

4点 p[0]〜p[3] から曲線を構成する点 pc(t) ただし tは0以上1以下 を求めるベクトルの計算(線形代数)アルゴリズムは Wikipedia を見るとこんな感じ。(参考、Wikipedia ベジェ曲線

p[4] p4 = p[0] + (p[1] - p[0]) * t p5 = p[1] + (p[2] - p[1]) * t p6 = p[2] + (p[3] - p[2]) * t p7 = p4 + (p5 - p4) * t p8 = p5 + (p6 - p5) * t pc(t) = p7 + (p8 - p7) * t

これをThree.jsベースのA-Frameで表現して、4点を持って動かせるようにしたら、ベジェ曲線エディタのできあがり!両手で直感的にぐねぐね動かしながら、自由に眺められるのが気持ち良すぎて危険なレベル。

PCでもベジェ曲線がでる様子は確認できますが、一度はぜひVRで、ご体験を!
(マウスで視点変更、カーソルで移動、ベジェ曲線編集不可)

<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>BezierVR</title> <script src="https://aframe.io/releases/0.9.1/aframe.min.js"></script> </head> <body> <script>'use strict' window.onload = function() { const scene = document.querySelector('a-scene') let p = new Array(4) let pnt = new Array(4) let lines = [] let line1 let line2 const init = function() { for (let i = 0; i < 4; i++) { if (pnt[i]) scene.removeChild(pnt[i]) } for (let i = 0; i < lines.length; i++) { scene.removeChild(lines[i]) } lines = [] const rndw = 1 for (let i = 0; i < 4; i++) { const x = Math.random() * rndw - rndw / 2 const y = Math.random() * rndw + .5 const z = Math.random() * rndw - 1 p[i] = new THREE.Vector3(x, y, z) let box = document.createElement('a-box') box.setAttribute('position', p[i]) const size = 0.05 box.setAttribute('width', size) box.setAttribute('height', size) box.setAttribute('depth', size) box.setAttribute('mixin', 'voxel'); scene.appendChild(box) pnt[i] = box } } const f = function(p0, p1, t) { const p0c = p0.clone() const p1c = p1.clone() return p0c.add(p1c.sub(p0c).multiplyScalar(t)) } const calcBezier = function() { const div = 40 let op = p[0] if (lines.length == 0) { for (let i = 0; i < div + 2; i++) { const line = document.createElement('a-entity') scene.appendChild(line) lines.push(line) } line1 = lines[div] line2 = lines[div + 1] } let col = '#ff0000' for (let i = 1; i <= div; i++) { const t = 1 / div * i const p4 = f(p[0], p[1], t) const p5 = f(p[1], p[2], t) const p6 = f(p[2], p[3], t) const p7 = f(p4, p5, t) const p8 = f(p5, p6, t) const p9 = f(p7, p8, t) let line = lines[i - 1] line.setAttribute('line', { start: op, end: p9, color: col }); op = p9 } col = '#80e000' line1.setAttribute('line', { start: p[0], end: p[1], color: col }); line2.setAttribute('line', { start: p[3], end: p[2], color: col }); } init() calcBezier() let np = -1 let mp = -1 setInterval(function() { let flg = 0 if (np >= 0) { const hp = handright.getAttribute('position') p[np] = hp.clone() pnt[np].setAttribute('position', p[np]) flg = true } if (mp >= 0) { const hp = handleft.getAttribute('position') p[mp] = hp.clone() pnt[mp].setAttribute('position', p[mp]) flg = true } if (flg) calcBezier() }, 1000 / 72) // 72Hz const selectNear = function(hand) { const hp = hand.getAttribute('position') let min = .5 let np = -1 for (let i = 0; i < 4; i++) { let d = p[i].distanceTo(hp) if (d < min) { min = d np = i } } return np } handright.addEventListener('triggerdown', function(evt) { np = selectNear(handright) }) handright.addEventListener('triggerup', function(evt) { np = -1 }) handright.addEventListener('gripdown', function(evt) { np = selectNear(handright) }) handright.addEventListener('gripup', function(evt) { np = -1 }) handleft.addEventListener('triggerdown', function(evt) { mp = selectNear(handleft) }) handleft.addEventListener('triggerup', function(evt) { mp = -1 }) handleft.addEventListener('gripdown', function(evt) { mp = selectNear(handleft) }) handleft.addEventListener('gripup', function(evt) { mp = -1 }) // B button handright.addEventListener('bbuttondown', function(evt) { init() calcBezier() }) } </script> <a-scene> <a-assets> <a-mixin id="voxel" geometry="primitive: box; height: 0.1; width: 0.1; depth: 0.1" material="shader: standard"> </a-mixin> </a-assets> <a-sky color="#335c7c"></a-sky> <a-entity id=handleft oculus-touch-controls="hand: left"></a-entity> <a-entity id=handright oculus-touch-controls="hand: right" laser-controls raycaster="showLine: true; far: .05" line="color: white; opacity: 0.75;"></a-entity> </a-scene> </body> </html>

1ファイル書くだけ簡単、WebVRでVR開発。オススメです!

links
- VRではじめる現代HTML入門 - Oculus Quest x 福井高専生
- 50行で作るVRマイクラ風 / boxcraft for Oculus Quest with A-Frame
- モバイル時代こそバス! つつじバスロケVRビジュアライズ - リアルタイムオープンデータ x Oculus Quest

神の視点が楽しいマイクラ入門、神様プログラミングの8x9クラフトに次ぐ第三段。 小学生がつくりたいもの上位の「マイクラつくりたい」に最新VR「Oculus Quest」で応えてみました。


白のブロックを自由に置けます。アンドゥーと全消しに対応して、JavaScript+HTMLで全プログラムでたった50行!


boxcraft for Oculus Quest - A-Frame
Oculus Questのブラウザーで、boxcraft.html を開き、右下のVRモードを選択するだけ!


トリガーでボックス設置。まちがったら中指ボタン。全消しはBボタン。

<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>boxcraft for Oculus Quest - A-Frame</title> <script src="https://aframe.io/releases/0.9.1/aframe.min.js"></script> </head> <body> <script>'use strict' window.onload = function() { const scene = document.querySelector('a-scene') const list = [] handright.addEventListener('triggerdown', function(evt) { const p = handright.getAttribute('position') const snap = 0.1 let p2 = { x: Math.floor(p.x / snap) * snap + snap / 2, y: Math.floor(p.y / snap) * snap + snap / 2, z: Math.floor(p.z / snap) * snap + snap / 2, } let box = document.createElement('a-box') box.setAttribute('position', p2) box.setAttribute('mixin', 'voxel') scene.appendChild(box) list.push(box) }) handright.addEventListener('gripdown', function(evt) { const b = list.pop() if (b) scene.removeChild(b) }) handright.addEventListener('bbuttondown', function(evt) { const boxes = scene.querySelectorAll('a-box') for (let i = 0; i < boxes.length; i++) scene.removeChild(boxes[i]) }) } </script> <a-scene> <a-assets> <a-mixin id="voxel" geometry="primitive: box; height: 0.1; width: 0.1; depth: 0.1" material="shader: standard"> </a-mixin> </a-assets> <a-entity id=handleft oculus-touch-controls="hand: left"></a-entity> <a-entity id=handright oculus-touch-controls="hand: right" laser-controls raycaster="showLine: true; far: .05" line="color: white; opacity: 0.75;"></a-entity> </a-scene> </body> </html>

VRフレームワーク「A-Frame」を使って、コントローラーのtriggerdownイベントを受け取り、a-boxを格子上に座標変換して設置するプログラムがコンパクトに組めます。


あるき回りながら、いろいろ見渡しながら、3次元空間に重力に縛られず、自在に作って遊べます!
次はカラーパレット?マイクラではできない箱の大きさ変更?派手な爆発エフェクト?
プログラミングで思いのままです!

links
- Oculus Quest | Oculus (64GB 49,800円、購入は公式サイトがオススメ)
- 「Oculus Quest」でVR体験が“爆上げ” 約5万円で最高級を楽しめる新時代に突入 その魅力に迫った (1/4) - ITmedia NEWS
- モバイル時代こそバス! つつじバスロケVRビジュアライズ - リアルタイムオープンデータ x Oculus Quest
- VRではじめる現代HTML入門 - Oculus Quest x 福井高専生

歩き回れて49,800円のVR、Oculus Questが到着。良いです。
複数ある外カメラによってモノクロですが外を見ることもできるので実質メガネ!(過言)

2880x1600のOLEDの画質は良く、ヘッドセットの装着感もよし、目の間の距離調整機構もあって、快適。
WebVR対応ブラウザが入っているので、アプリづくりも手軽にできます!
リフレッシュレートは72Hzとパフォーマンスに合わせて控えめになっていますが、スマホの60Hz以上なので十分あり。


test with React VR
アプリ起動して、見渡している様子。スマホにミラーリングできるので、そのまま画面録画。
Oculusと同じFacebook社による「React 360」なので安心。
サンプルを混ぜて、静的ページとして生成しました。


デモ、3枚目の写真は、京都のお寺、7,250円で買えちゃうお手軽360度カメラで撮影したものです。(最高画質、40M画素なのでもっと画質が高い変換方法模索予定)


Oculus Goと比べて、大きくなった箱。


高級感あって収まりも良し。

2016年に作った巨大jig.jpロゴも、アプリ一切触ることなく歩いて見渡せるようになりました。
VR jig.jp BIG logo - A-Frame

自分だけの空間創り放題、公開し放題。これはかなり良いですよ!
Oculus Quest

世界をつないだOS、web。
JavaScriptを使って創れば世界中のPC、スマホを持ってる人に届けられます!

日々アップデートされる、JavaScript用の数々な便利ツール。 そろそろリニューアルを考えている本ブログ、静的ページ生成もサクッとこなしてくれるという Nuxt.js の前段として Vue.js はじめ。

日本コミュニティがしっかりしていて、本家ドキュメントがわかりやすい!
はじめに — Vue.js

ひとまず、ネパールの車のナンバーや、お札など、まちなかでも良く見かける、ネパール数字変換アプリを、漢数字変換アプリをもとにつくってみます。

Vue.js を使い始めは簡単。1ファイル vue.js を読み込むだけ!

<meta charset='utf-8'/> <div id="app"> <input id="jp_num" v-model="num"><br> <span id="nepali_num">{{ npnum }}</span><br> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script>"use strict" const toNepaliNumber = function(s) { return s } new Vue({ el: '#app', data: { num: "192.168.0.1", }, computed: { npnum: function() { return toNepaliNumber(this.num) } } }) </script>

v-model や、 {{ }} を使って、HTMLとJavaScriptをつなぎます。
数字をネパール数字に変換するJavaScriptのメソッド toNepaliNumber を実装して、できあがり!

const toNepaliNumber = function(s) { const NEPALI_NUM = "०१२३४५६७८९" let res = [] for (let i = 0; i < s.length; i++) { const c = s.charCodeAt(i) - "0".charCodeAt(0) if (c >= 0 && c < 10) res.push(NEPALI_NUM[c]) else res.push(s.charAt(i)) } return res.join("") }

to Nepali Num (base)」 → to Nepali Num (with CSS and so on..) Vue.js の真骨頂は、配列や複雑なデータ構造も View としての DOM に即反映されるところ。
いろんなデータをきれいに整理したwebサイトやwebアプリ、更にすばやくたくさん作れそう!
PCN大阪、森さんの本もどうぞ!「動かして学ぶ!Vue.js開発入門 (NEXT ONE)

世界中のプログラマーが自らの道具を創り、磨き、シェアされ、それらを使って一段と強い道具を作るループは、構造的に高速化するしかありません。 ぜひ、この輪に加わわっちゃいましょう!

はじめての JavaScript のための、時計、地図、AR、ゲームなど作成用シンプルフレームワーク jigjs もどうぞ!

links
- Vue.js
- jigjs - Numbers in Nepali language on IchigoJam

ある地域のカラム地図を作る際、悩ましいのは縦横をいくつにするか。
東京23区であれば、かけると23以上になる比較的近い整数2つを選ぶことになるが、網羅性を検証しようとすると地味に面倒な課題。

そんなときには、プログラミング!
面倒事対処にもってこい!


逆かけ算 - カラム地図用

まずアルゴリズムを考える
1. 平方根であたりをつける
2. その前後をかけ算して、収まる組み合わせリストを作る
3. 余りが少ない順にソートする

実現しやすそうなプログラミング言語でつくる(今回はJavaScriptをセレクト)

const n = this.value // 1. 平方根であたりをつける const m = Math.floor(Math.sqrt(n)) // 2. その前後をかけ算して、収まる組み合わせリストを作る let s = [] const width = m for (let i = -width; i <= width; i++) { const a = m + i if (a < 1) continue for (let j = i ; j <= width; j++) { const b = m + j if (b < 1) continue const c = a * b const d = n - c if (d <= 0 && -d < n) s.push([ d + (a - m) / 100, a + " x " + b + " = " + c + " = " + n + (d <= 0 ? " - " : " + ") + Math.abs(d) ]) } } // 3. 余りが少ない順にソートする s.sort(function(a, b) { return b[0] - a[0] })

十分な速度と精度がでれば完了!
(速度や精度が不十分なら、アルゴリズムを改良する。検証もプログラミングでやると楽!)

北陸三県カラム地図へのご意見ありがとうございます!
やはり地元の人の力、大事ですね!

GW明けの5/10、高専生企画で楽しいIoTプログラミング伝授に兵庫県、明石高専へ行きます!

全国の高専生のご要望にできるだけ応えたいと思いますが、1年で全部はとても回りきれないので、アプリ開発の経験を積んで、IchigoJam伝道師にもなれちゃう「高専インターン」がオススメ!
全国高専生向けjig.jpインターンプログラム2019 ~募集開始のお知らせ~

links
- 地図の新表現「カラム地図」で辿る世界、日本、北陸三県
- 日本は1%マイノリティー時代へ、高専生インターン募集開始!

開発中のカラム地図世界版、エリア毎に塗ってみました。
TabularMaps - 8bitのCSVデータと、ISO3166-1を元にCSV化したiso3166.csvを使った、世界カラム地図


世界カラム地図β
* XK は、コソボ共和国の表すが、ISO3166としては未定義。KV となるかも?(‘XK’ country code for Kosovo | GeoNames Blog

誰も置き去りにしない「SDGs」のダッシュボードに!
いろんな世界のデータをビジュアライズしてみましょう!

ISO3166は、国名が2桁または3桁で割り振られ、その1段階細かい区域がコード化されています。国名はISO-3166-1、日本の場合は都道府県がISO_3166-2:JPとして定義されてます。カラム地図のズーム表示に使えそうです。

ISO3166準拠のオープンデータは、国として公開したいところですね!
データセット - DATA GO JP」 2019.4.20現在、データセット見つからず。

ジオ展2019OSGeo.JPブースにてお披露目された地図の表状表現「カラム地図」。

世界196カ国、日本47都道府県、福井県内、市内、町内とどんどんズームレベルを変更できるとオープンデータなど、可視化、ダッシュボード化に便利です。

xということで、まずは身近な福井県内17市町のカラム地図!

福井カラム地図」 カラム地図5x4
嶺南と嶺北の2つのエリア分けと、JRのラインを意識した作り。
福井県民が見てもだいたい納得の配置なはず。


見に行ってくれた @satoshocoさんの出身地、広島版、作ってみました!


広島カラム地図β」 カラム地図5x5

広島市内にある府中町をどう配置する?どちらを上にする?市同士のつながりは?
地理だけでは見えないので地元の人ではないと完成できないパズル。
よって、こちらは未完成のβ版。

広島県の方、みんながそこそこ納得いくカラム地図として、ぜひ完成させてください!
ソースは、GitHub上に。どうぞ地元のカラム地図づくりも!(ネパール版もつくりかけ

links
- 日本の都道府県を7x7からむ地図として表現! 測量部担当地域と八地方区分
- tabularmaps/hq: カラム地図のホーム

ネパールにもあるオープンデータサイト「Open Data Nepal
英語で書かれていて、すっきりしたデザインで見やすい!

こちら「Number of Students Enrolled in Primary School by 75 Districts 2003 to 2015 - Datasets - Open Data Nepal」を、ネパール75のprovince(県?)をカラム地図にしてみたものα版。

Primary School Kids in Nepal - TabularMaps

ひとまず順番に並べただけなので地理的位置関係を表していない暫定バージョン。ネパールに詳しい方、ぜひ位置情報カラム状に並べた案、教えてください。 (ネパール、ベース地図


こちらはExcelでグラフ化したもの。一番上のラインは右軸でトータル。2010年をピークに全体の小学校に通う子供の和は減少傾向。その中、カトマンズは伸びている。 日本の二の舞は避けたい。


電気街でステキのマスターに会った!


話が合う予感がしたので、IchigoJamの話をしたら、BASICの話が通じ、早速店の若い定員に説明してくれた。


オリジナル製品を作っているエンジニアでもあるマスター。強力な協力者になってくれそう!
マスターオリジナル、電圧計付きの電源タップ、なぜか17Vしか来てなかったりするネパールでは重要機能!


お店の名前は、CPL、Computer Printer Laptopの略!カトマンズに来た際にはぜひお立ち寄りください!


場所はカトマンズの秋葉原、電気街 New Road。こちら最初に発見した、大きめのコンピューターショップ、SHIFT Technology Pvt. Ltd. PS/2キーボード、1つ300ルピー、約300円、在庫多数!


そのすぐ側、ZENITH SUPPLIERS でも、PS/2キーボードと言ったらすぐに出してくれた。


キートップにネパール文字!ブランド名はエベレストとネパール語で書いてあると教えてくれた!お土産にもオススメ。


電線がすごい。停電したり、コンセントに電気が来てなかったりは当たり前。ある意味、電気が身近でよい。


モバイルバッテリーを持ってこれない分、電源は大事!
いろんなコンセントに対応できるようにしておきたい。緩かったりするので、養生テープは大事。


こちら路上で購入した安物の電源タップ。CPLのマスター曰く、銅の含有率が低いらしい。相場80ルピーとのこと。300で買ってしまった。

いろいろお店を巡った結論、PS/2キーボード、ネパールには豊富!
そして、安い!300ルピーあたり、約300円で購入可能。
IchigoJam at Nepal、いいかも!

ネパールへ初入国した今日、西暦2019年4月14日は、ネパール公式のピクラム歴2076年1月1日!
まちなかで聞こえる「Happy New Year!!」の声!

1ヶ月が32日あったり、カレンダーがまるで違っていておもしろい。(2076年2月は32日まで
もし歴がこのままだと、25年後、ネパールは一足先に22世紀を迎えることになる。

タイムゾーンもユニークで、国単位では世界唯一の15分刻み、GMT+5:45を採用。
 結果、日本との時差は3時間15分、時計を90度ひねって読むと、ネパール時間になる!


npljpnclock」 - by egclockjs
濃いほうがネパール時間。薄いほうが日本時間。ちょうど90度ずれる。


ネパールのトリブバン国際空港、「ようこそ」の文字でも迎えてくれた。


さすが新年活気がある!大晦日の昨日はもっとすごかったらしい。


ネパールのビール、エベレストで乾杯!


明日から活動スタート、ネパールのこどもたちへプログラミングを伝える、KidsVenture&PCNチーム!

links
- KidsVenture
- PCN

Tweet
クリエイティブ・コモンズ・ライセンス
この作品は「Creative Commons — CC BY 4.0」の下に提供されています。
CC BY 福野泰介 - Taisuke Fukuno / @taisukef / アイコン画像 / プロフィール画像