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

49,800円という衝撃価格のモバイルVR「Oculus Quest」が好調

開発の楽しさを伝えるため、50行マイクラ風に続く第二弾、今回はVRらくがきアプリを48行で作成。
Tilt Brushは気持ち良いけど、起動に時間がかかるのがネック(あと、有料)。
今回作った、お絵かきツールは、超軽量なので起動も一瞬!(無料&オープンソース on GitHub

drawline-VR
フレームワーク、A-Frameを使っている。線をa-lineでだらだらと追加しているが、割りとすぐに重くなってしまうのは、どうにかできるのか!?フレームワークやWebVRの限界なのかも?


さらさらと描く様子を、本体へ録画して、USBケーブル転送。(転送は開発モードをOFFにしてAndroid File Transferを使用)

<!DOCTYPE html><html><head><meta charset="utf-8"/> <title>drawline-VR for Oculus Quest</title> <script src="https://aframe.io/releases/0.9.2/aframe.min.js"></script> <script>'use strict' const list = [] let line = [] let bkp = null AFRAME.registerComponent('input-listen', { init: function() { this.el.addEventListener('triggerdown', function(evt) { bkp = handright.getAttribute('position').clone() list.push(line) }) this.el.addEventListener('triggerup', function(evt) { line = [] bkp = null }) const removeLine = function() { const line = list.pop() if (line) for (let i = 0; i < line.length; i++) document.querySelector('a-scene').removeChild(line[i]) return line } this.el.addEventListener('gripdown', function(evt) { removeLine() line = [] bkp = null }) this.el.addEventListener('bbuttondown', function(evt) { while (removeLine()); }) }, tick: function() { if (bkp) { const p = handright.getAttribute('position').clone() const aline = document.createElement('a-entity') aline.setAttribute('line', { start: bkp, end: p, color: "#FFF" }) document.querySelector('a-scene').appendChild(aline) line.push(aline) bkp = p } } }) </script></head><body><a-scene> <a-sky color="#546c4c"></a-sky> <a-entity id='handright' oculus-touch-controls='hand: right' input-listen></a-entity> </a-scene></body></html>a

ご自由に改造、活用ください!

福井県の昭和おもしろスポット2箇所紹介。

こちら福井県庁内1Fにある喫茶店。昭和な雰囲気。


なぜかダンベルが!?レトロなレジも必見です。


懐かしの2つの時計が掲げてあったお店を発見、世代が違うと全くわからないことがわかった。(on Twitter)

links
- 一日一創 VRカテゴリ
- 一日一創 VRアプリ一覧

まずはゲームを作ってみたい。だったら、思う存分作ってみよう!

ゲームづくりに含まれるプログラミングテクニックは、様々なアプリケーションづくりに応用可能。
快適に動作させるためにアルゴリズムを工夫することは、サービス運用時のコスト削減に直結。

パソコンを持っている高専生にオススメは、作ったアプリを友達に自慢できるJavaScriptを使ったwebアプリ。
eggamejsとして、かんたんゲームフレームワークを提供します。

サンプルアプリ、ワンキー弾幕ゲーム「dnmk
タップや、クリックでちょっと浮かびます。狙ってくる弾を可能な限り避けよう。


egclockjs
時計アプリをオリジナルでつくってみようという課題作品を掲載しました!

プログラミング言語も語学の一種、英語と一緒で使えば使うほどに楽に使えるようになりますよ!
まずは一週一創あたりから作るペースを身に着けよう!

今週は、eggamejs の作品募集!
GitHubアカウントをつくって、forkして、改造して、READMEへ「プルリク」ください!
質問は issues へどうぞ。

福井高専1年生からリクエストあって、プログラミング入門。
HTMLで3D空間は思いのまま!JavaScriptを使ったオリジナルwebアプリで自慢しよう!

1. 締切は守る
2. まず自分で調べる
3. 失敗するほど成長する


3D HTML入門でテンション上がる、福井高専生

作ってみたいもの、作りたいもの、とりあえず勢い、なんでもいいので、いろいろチャレンジ!
やればやるほどやりたいこと、やると楽しいことが見えてくる。


Webアプリはじめのいっぽ HTML+JavaScript
50行でつくるVRマイクラ風、IoT、スマホのゲームもHTMLとJavaScriptを使えば作れちゃう!
大文字小文字の違い、空白の有無に気をつけて!


3D雪だるまづくりでHTML入門を追え、次はJavaScript!ゲームに必須な Math.random() でググり方を体験したら、オリジナルサイコロアプリづくりに挑戦。 画像づくりの制限時間5分。締切は、過ぎたら0点というゲーム!


The-Dice」 by 福井高専学生
開いたら1から6までの目が出る。PCでもスマホでもゲーム機でも動く、立派なwebアプリ。


GitHubはじめのいっぽ
作ったwebアプリは、じゃんじゃん公開していこう!GitHubのアカウントをつくって、初アプリをコミット!

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

一日一創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現在、データセット見つからず。

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