2012年05月18日

Vectrex

こんにちは、Hexaレトロゲーム部のKayanuma.です。

20120518_vec03.JPG

今回は思いっきり趣味に走ったネタをご紹介しようと思います。
写真はVectrexというベクタースキャン方式を採用した家庭用ゲームマシンです。
http://en.wikipedia.org/wiki/Vectrex
日本名は光速船、
http://ja.wikipedia.org/wiki/%E5%85%89%E9%80%9F%E8%88%B9
このレトロで未来的なマシンは1982年に発売されました。
ブラウン管に蛍光で浮かび上がるワイヤーフレームグラフィックスがSFチックでとても美しく、
魅了された多くのファンがいます。(私もその一人)

XYの電圧で画面に軌跡を描く方式はオシロスコープのそれと似ています。
最初期のビデオゲーム、Tennis for Twoはオシロスコープを画面出力に流用したものだったそうです。
http://ja.wikipedia.org/wiki/Tennis_for_Two


ベクタースキャンは当時の非力なCPUでダイナミックな動きを可能にする期待された方式でしたが、
市場ではカラフルな色を扱えるラスタスキャン方式が歓迎され、ゲーム用途としては完全に淘汰されてしまいました。

ビデオゲームのIFとして、もしもベクタースキャンが勝っていたらどうだったでしょう。
きっと影響はビデオゲームに収まらず、コンピュータも違う進化をしていたかもしれないなと夢想したりして・・。


因みにVextrexには別売りで3Dグラスが存在していたりします。
残像を利用した片眼ずつ時分割する方式ですが、今のような液晶シャッターは使えなかったので
スリットの入った円盤をモーターでグルグル回していたそうです。
なんともダイナミックでプリミチブ!ですね。



昨日ブログのネタにと真夜中に押入れからゴソゴソと引っ張り出してきたのですが、久しぶりに起動したらつい遊んでしまいました。
posted by 管理人 at 20:30 | 日記

2012年05月17日

トイ

こんにちはひらめき
シュンスケですぴかぴか(新しい)


突然ですが、トイカメラという言葉をご存じでしょうかサーチ(調べる)
明確な定義まで把握してませんが、トイカメラ自体は新しいものでは無く、
安価な材料や仕組みで作られたカメラ製品全般の事ですカメラ

その為、撮影した写真の品質に大きくバラつきが出るのが特徴で、
撮るごとに写り具合が変わり、味があって趣があるとして、好きな人も
多いようです目

今ではデジタルカメラが普及していますが、機能としてトイカメラ風の写真が
撮れたり、そういったエフェクトがかけられるカメラが多く出てきています。
そういうカメラはトイデジと言うそうですね映画

そんなトイカメラですが、iPhoneを使ってトイカメラ風の写真が撮れるという
アプリがありますCD

無料だと、「Instagram」というアプリが有名です携帯電話

トイカメラの特徴である、変わった色調やぼかしなどのエフェクトがかけられ、
ミニチュア風な風景や、レトロな雰囲気も出せまするんるん

カメラについては全くの素人ですが、会社の近くを少し撮影してみましたビル
ぱちり
20120517_img4.JPG20120517_img2.JPG


こうやって色々とエフェクトをかけていると、ゲーム画面に様々なエフェクトを
かける場面を思い出しました晴れ被写界深度やカラーフィルタ、ブラーなどなど。
どういったエフェクトをどういった具合にかければどんな見え方をするのか、
このカメラから学べる事も多そうです決定

人口総カメラマンの時代に、少し趣を変えた写真を撮ってみてはいかがでしょうかわーい(嬉しい顔)
posted by 管理人 at 23:30 | ソフトウェア紹介

2012年05月16日

メモリイメージ

日に日に気温も上昇し汗ばむ季節になってきましたね晴れ
汗かきなので既に薄着になりつつある「オクダ」です。
皆さんは夏に向けてのカラダ作りは大丈夫ですか?
今年はプロジェクトが佳境を迎えるのであきらめムードですふらふら

今回はプログラマ向けの少しディープな話をしてみようと思います。
テーマは「メモリ」です。
皆さんがPCを使ったりプログラムをしている時にメモリを意識する事は少ないかもしれませんが、
メモリとうまく付き合っていく事で、更に上位レベルのプログラマになれると思います。
プログラムの最適化や言語仕様の理解、デバッグに役立つと思います。

C言語(C++)を基準に解説していきますが、他の言語でも共通する考え方だと思います。
OSやライブラリはの大部分はC(C++)で作られているのでほとんどの言語がCのメモリ管理を踏襲しています。
CPUやコンパイラによる細かな違いもありますが、大きくは変わらないでしょう。


プログラムがシステムからメモリ上にロードされ動作を開始するタイミングでは大きく分けて4つのメモリ領域が確保(割り当て)されます。

1プログラムの命令部分
CPUはここに書かれた命令を一つずつ順番に処理していきます。
稀に、この領域に固定の値が含まれる事があります。(関数のstatic constなローカル変数など)

2固定された値
constな変数がここに分類されます。
固定のテーブルなどはココです。
この領域の内容が書き変わる事は無いハズですね。

3変数領域
globalな変数の領域です。
関数内のstatic変数やC++のstaticなクラスメンバもココになります。
関数内のstatic変数はコンパイラや最適化具合によって1の内部に分散格納される場合もありますが、場所の問題であって意図としては同じです。


4スタック
謎の領域「スタック」です。
基本的に固定された領域ですが、使い方がトリッキーで詳しく説明されない事も多いです。
次回はココにスポットを当てたいと思います。

更に実行時に割り当てられるメモリがあります。

5ヒープ領域
mallocやnewなどで実行時に動的に割り当てられるメモリ領域です。
mallocの場合はメモリ確保のイメージがあると思いますが、
newの場合はメモリ確保している印象は希薄だと思います。
また、関数内で宣言したクラスは宣言タイミングでヒープからメモリ確保され、スコープを抜けるタイミングで解放されます。
constructor,destructor(new,delete)がその都度呼ばれている事に注意しないと痛い目を見ます。

自分がプログラムの中で書いたコードや確保したメモリが
どういった役割を持っていて、どのような場所に確保されているか、、、
少しだけイメージできたでしょうか?
値が変更される可能性があるのか無いのか。
静的に確保されるのか動的に確保されるのか。
このあたりの違いがカギになっているようです。
バグが発生した場合の解決の糸口になる事もあるので、少しだけ意識してみるといいでしょう。

さて、今まで説明してきた中で触れていないモノがあります。
「staticでないローカル変数」です。
最適化された場合にはメモリではなくレジスタに割り当てられることも多いですが、
実は4のスタックに確保されることがほとんどです。
また、レジスタに割り当てられたとしてもスタックと無縁ではありません。
むしろ密接に関係しています。
次回はこの「スタック」の役割と仕組み、動作にスポットを当てたいと思います。
乞うご期待!
posted by 管理人 at 16:19 | プログラミング

2012年05月15日

視点

こんにちは。さいやん、こと齊藤です。

昨今の円高で日本のものづくりの危機が叫ばれていますがく〜(落胆した顔)
日本でものを作っても、円高では海外に売る場合に
利益を圧迫することになるからです。
 1$ = 100円のときに80円の原価でものを作って1$で売れば
 日本円にして100円で売れるので20円の利益が出ますが、
 1$ = 80円(円高)のときに80円の原価でものを作って1$で売っても、
 日本円にして80円にしかならず、利益は出ないからです。
 円高前から輸出で利益を上げていた企業は利益が出なくなって
 きていることが分かると思います。

すなわち、円高の現状では今までの商売が成り立たなくなってきますあせあせ(飛び散る汗)
さて、どうすればいいのでしょうか。
価格競争ではなく他には真似できない技術で勝負し、
オンリーワンの価値ぴかぴか(新しい)を売り込めるようになるといいのではないでしょうか。
では、オンリーワンの価値はどうやって生み出せばいいのでしょうexclamation&question
この問いに簡単に答えられれば苦労しません…ふらふら
しかし、ヒントひらめきはあります。

最近では「生物模倣」と言われる手法で様々なものが生まれています。
トンボの羽を模して作られた風車は極微風でもとらえることができ、
効率よく回ることから従来以上の効率的な風力発電が可能になりました。
蚊の口を模して作られた注射針は痛みを大幅に軽減することが
可能になりました。

世の中の事象で、「どうしてだろう?」と疑問を持つことは
非常に大切だと思います。
生物模倣は生物の構造を研究し、学ぶことで新しい技術に
昇華させることですが、身近なことでも、
「あの人はどうしてあんなに仕事ができるんだろう」
「あの会社はどうしてあんなに儲かっているんだろう」
「あのゲームはどうしてあんなに面白いんだろう」
と疑問を持って研究することで、見えてくるもの目があると思います。

少し視点を変えるだけで、他者とは違った結論にたどり着く。
そこから生まれる独自性に価値が生まれたとき、
イノベーションとともに新たな領域に踏み出せるパンチのではないでしょうか。

専門家として、ある一点を掘り下げることも大切ですが、
視点を変えることで見えることも大切にしていきたいと思いますexclamation
posted by 管理人 at 11:18 | いいモノづくり道

2012年05月14日

へこたれそうなとき読んでみて!

初めまして!大阪デザイナーの阿部ですかわいい

ヘキサとご縁があり半年とちょっと、もうそんなに時間が経ったのかと驚いております。時計

さて、このブログは学生さんが多く閲覧されているということで、学生さんに向けてのお話を書きます。

皆さんは夢を叶える上で一番大切なことは何だと思いますか?
才能?経験?学歴?
いえいえ、一番最初に必要なのは
「夢を持つこと」
え?!何それ?!当然じゃないの?!ちっ(怒った顔)ってなるようなお話なのですが
夢を持つこと、持ち続けることは実はとても難しいことなのです。

夢を叶えるために起こす行動の中には、上手くいかないこともあるでしょう。
むしろ、上手くいかないことの方が多いぐらいです。
そんな中で、「この夢をあきらめてしまおうか」「もっと楽な道にしてしまおうか」等々
誘惑は数知れず、そんな誘惑に負けて「行動することを止めてしまう」そしてその内「夢」が本当に「ただの夢」になって、「そんな夢もあったなぁ」とただ思い出すだけになってしまうのです。

文中でさらりと流しましたが「夢を持つこと」の次に大事なのが
「行動すること」そしてその次が「行動を続けること」

夢に向かって行動し続けること、それを一言で言うと「努力」になりますね。
才能も大事ですが、努力ができなければそれも台無しになってしまいます。
その大事な「努力」の一番最初に来るのが「夢を持つこと」なのです。


以上のこと、別に私が考えたことではなくて

この本から学びました

「思考は現実化する」


とても有名な本なのでご存じの方も多いかと思いますが
未読の方は是非読んでみて下さい。プレゼント
へこたれそうなとき、もうちょっと頑張ってみようと元気が出ますよ!手(グー)

ではでは!



posted by 管理人 at 16:36 | 日記

2012年05月11日

PSS

こんにちはわーい(嬉しい顔)
今月頭の暖かさに乗じて冬服を片付けて夏服を引っ張り出して来たものの、最近また冷え込んできている為朝晩は震えているがく〜(落胆した顔)マイキーですexclamation
流石に上着はカムバックしてもらいましたブティック
*-*-*

さて、少し前の話になりますがPlaystation.comにてDeveloper Programに含まれる開発リソースのベータバージョンが公開されました
こちらはPC向けの各種開発用アプリケーションとライブラリ、サンプルコード等が含まれる「PlayStationSuite SDK」と、それらを用いて作成したアプリケーションをPlaystationVitaや一部Andoroid端末で動作させる為の「PlayStationSuite Development Assistant」が含まれます。
また、開発者同士で目情報交換耳を行う為のフォーラム「PlayStationSuite Developer Forums」も用意されています。
これを初めて見たとき、思わず
お家でこれだけの開発環境が使えるなんて、なんて素敵なんでしょうぴかぴか(新しい)
と声には出しませんでしたが、非常に興味をそそられました。

今回公開された開発環境は携帯端末携帯電話向けのものですから、手軽に多くの人に見せる事ができる、見せてもらうことが出来るのが魅力的ですね。
特にVitaで動作させることが出来る、つまり市販の携帯ゲーム機で動作させることが出来るという所に非常に惹きつけられます。
他にも、開発者同士で情報交換を行う場が用意されているのがありがたいです。
一般的に広く頒布されている開発環境は、諸々の情報が四散してしまっている事が多く、情報収集に時間を要してしまう事が多くありましたふらふら
ですが、今回のように初めからこのような場が提供されていれば、情報が集約されている事が期待出来そうですグッド(上向き矢印)グッド(上向き矢印)

思い返せば、自分の作った物を見せる為、PCの前まで人を連れてくるのに一苦労した覚えがあります。
相手がPCを持っていればデータを送りつけて遊んでもらう事も出来たのですが、私の場合「ゲームはするけどPCを持っていない」友人が大多数でしたので、色々と工夫をしなければなりませんでしたあせあせ(飛び散る汗)
先程書きましたように今回公開された開発リソースは携帯端末向けの物ですから、「見せる、遊んでもらう」という点において苦労する事は少なそうです。
プログラミングを嗜んでいてゲーム開発に興味のある方は、この機会にDeveloper Programに触れてみてはいかがでしょうかパンチ
posted by 管理人 at 21:47 | 日記

2012年05月10日

メールの確認術

こんにちはexclamation藤原です。

今年は梅雨入りが例年より早く、沖縄ではもう4月末に梅雨入りしましたね。雨
このままいけば大阪も5月の後半に梅雨入りしそうです。
湿気でジメジメしたのは苦手ですがふらふら雨は好きなので関西のアジサイ寺かわいい巡りでも
しようかと計画中です。グッド(上向き矢印)グッド(上向き矢印)


さて、今回は大量のメールを確認する術をご紹介したいと思います。
仕事をこなしていくにつれ大量の仕分けフォルダを作ったり、
何度もメールを確認したりした事は無いでしょうか?目

大量のメールに悩まされているアナタに贈る10のメール整理術
http://www.lifehacker.jp/2011/11/111102email-overload.html

Gmailに学ぶ――大量のメールに振り回されない基本テクニック
http://bizmakoto.jp/bizid/articles/0608/01/news014.html

紹介ページに書かれている内容は基本的な事が主ですが
その中でも私が参考にし普段心がけている事は

・受信トレイは空にする
・返信は素早く行う
・確認したメールは優先度で仕分け
 受信トレイ
  ├─アーカイブフォルダ
  ├─要対応フォルダ
  └─保留フォルダ

以上の3点になります。

これだけでメールをかなり整理でき、担当範囲の対応が遅れる事が無くなりました。ひらめき
色々な手法があると思いますが、以上一つの例として参考になればと思います。わーい(嬉しい顔)
posted by 管理人 at 14:05 | 日記

2012年05月09日

新たな暗算方法

先週のGWに、久しぶりに大学の友人に会ってきましたわーい(嬉しい顔)
アメリカからのお土産で本場テキサスのカウボーイハットをもらい
ガンマンの気分を味わいながら飲み明かしていましたビール
やはり、日頃はあまり会えない友人と飲むのは良いですねるんるん
お久しぶりです。マックスです。


さて、最近、このような記事を見かけました。
http://zasshi.news.yahoo.co.jp/article?a=20120425-00000001-president-bus_all

簡単に内容を説明すると、2桁×2桁の掛け算を暗算で行う方法が新たに提案されたという記事です。
その計算方法の名前は「ゴースト暗算」ですぴかぴか(新しい)

日本では学校で九九までを暗記し、インドでは19×19までの計算を暗算でできるそうですが
それよりも範囲の広い99×99までの暗算方法が提案されたということで話題になっていました耳

私も記事を見て気になり、実際にゴースト暗算を解説している本を購入してみました手(グー)

ゴースト暗算.jpg


このゴースト暗算では、プレートを頭の中にイメージし、その中に数値を入れ、計算します。
2桁×1桁のゴースト暗算に関しては、youtubeでも無料で公開されていますので
こちらを見るとプレートが何を意味しているのか理解しやすくなるかと思います。

  youtube: http://www.youtube.com/watch?v=R3T8kgclG6o

2桁×2桁の暗算では、このプレートの使い方を応用して暗算を行います。
詳細な暗算方法に関しては、ここで説明する訳にはいきませんので、書籍を購入して
ぜひ自分の目で確認してみてください目


プログラマという職業柄、計算とは離れられない関係にあります。
もちろん電卓などを用いて正確に計算することに越したことはないですが
ある程度の単純な計算は、暗算で行うことで少しでも作業の効率化につながるかと思います。
(ゴースト暗算は学校で習う筆算とは異なる方法で計算を行うため、個人的に慣れるにはまだ時間がかかりそうですが…ふらふら
これからも新しい発見や技術に目を向け、触れていくことができればと思いますパンチ
それではまた手(パー)
posted by 管理人 at 21:27 | 日記

2012年05月08日

ものづくりを楽しむ

おはようございます!マーシーです。

GW中、普段は時間の都合で中々会えない友人達と久しぶりに再会することができました。
仕事の業種は違うのですが、みな自分を高めるために努力していると聞き、
自分も負けられないと気が引き締まる思いでしたパンチ
友人達に自信をもって紹介できるゲームが作れるようにより一層頑張りますexclamation


私は本が好きなので、よく本屋さんへ行きます。
その場で気に入ってしまい、しばしば予定になかったものも買ってしまうのですが、
今回、また衝動買いをしてしまいました目

20120508_1.jpg

…はい、本じゃないです。
最近の大きな本屋さんでは、本以外も見かけるようになりましたよね。
これもその中の一つで、「nanoblock」と言うそうです。
名前の通り非常に小さなブロックで、一つのポッチが4mmx4mmしかありません。
子供が遊んでいるとすぐに失くしてしまいそうですふらふら
ですので、対象年齢は12才以上となっています。

写真は「セキセイインコ」で、
他にも「パンダ」や「アヒル」といった動物や、
「姫路城」や「東京スカイツリー」といった建物もあり、
本屋さんでは完成品が展示されていました。
(中には「サグラダファミリア」なんてものも!完成品?なのか…。

ブロックと言うと
昔は子供のおもちゃというイメージがありましたが、
今は「LEGO」を筆頭に大人も楽しめる娯楽になっているように思います。
実際自分で作ってみると、
童心に返ったかのようにブロックを積んでいました。

最近では「Minecraft」といったゲームもありますね。
このゲームもブロックを積み上げて、何かを作ることができるのですが、
ユーザーの中には、実際の町をブロックで再現しようとしている人もいるそうです。

思うに、完成させるのが目的であるのでしょうが、
作っている途中もやっぱり楽しいのでしょう。
それは子供だろうと大人だろうと変わらないのだと思いますわーい(嬉しい顔)

私達の仕事も物作りです。
最終的にはユーザーのみなさんに楽しんでもらえるゲームを作るのが目的ですが、
作っている最中、私達も楽しんで作っています。

楽しく作ったもので、
さらに多くの人に楽しんでもらえるのであれば
これほど嬉しいことはありません。

そんなことを考えながら、
「nanoblock」を作っていると
すぐに完成してしまいました。

20120508_2.jpg

これからも楽しく、そして楽しんでもらえるものを作っていきたいと思いまするんるん
posted by 管理人 at 12:58 | 日記

2012年05月07日

JavaScriptで3D

突然ですが、ベランダで野菜を育て始めましたクリスマス
少しずつではありますが、元気に育っていく野菜を見るのが楽しみなgood sun晴れこと山口です。

さて少し前からJavaScriptを話題にしているのですが、
今回は前回のドラッグ&ドロップを引き継ぎつつ、今までと違ったJavaScriptのサンプルを用意しました。
お待たせ致しました、ついにWebGL到来です!!
ついにブラウザだけの力で3D表示出来る時代の波に少しだけ乗っかってみました。
その為今回のサンプルが動作するブラウザは限られてしまいます。
推奨ブラウザはGoogle Chromeとなります。

サンプルはこちらから

今回のサンプルは実行されると四角い箱が回っていますプレゼント
ここにブラウザで使用可能な画像ファイル(.png等)をドラッグ&ドロップすることで、
画像をテクスチャとして貼ることが出来ます。
※簡単に試してみましたが、どうもjpegは白い画像になってしまうようです。。。pngでお試し下さい。

ドラッグ&ドロップについては
最後に掲載するソースコードのdropFileの部分を参照して下さい。
dropイベントを受け取って、
中身が画像であればテクスチャを作成しています。
実際に一連のソースコードがあると、
どのような流れで動いているのか分かりやすいのでは無いでしょうか。

今回サンプルを作っていて、昔Java3Dでブラウザに3D表示をしていた時の事を思い出したりしました。
いまではJavaScriptで3D表示が出来ておまけにシェーダが使えてしまうのですから、
技術の進歩は凄まじいものです。

更にJavaScript版COLLADAローダというのもあるようです。
頑張れば3Dモデルデータもブラウザにドラッグ&ドロップで表示出来るようになってしまいます!
これは益々目が離せない感じです目

WebGL入門も果たしブラウザ熱が上がってきたところで今回は終了とさせて頂きたいと思います。
次回もWebGLについて書ければ良いなぁと考えておりますが、予定は未定です。


最後に注意点及び、今回のサンプルのソースコードを掲載します。
まず注意点ですが、
このサンプル、Google Chromeではサーバにソースコードがある場合は問題なく動作しますが、
ソースをローカルにダウンロードして動作させようとした場合に通常はドラッグ&ドロップが働きません。
MacOSXの場合は以下のようなシェルスクリプト経由で起動させることでファイルのドラッグ&ドロップを受け付けるようになります。

#!/bin/sh
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --allow-file-access-from-files

そして以下が今回のサンプルのソースコードになります。
今回のサンプルは行列処理にNewBSDライセンスにて配布されているglMatrixを利用しています。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>javascriptサンプル</title>
<script type="text/javascript" src="http://glmatrix.googlecode.com/files/glMatrix-0.9.5.min.js"></script>
</head>
<body>
<canvas id="canvas" ondragover="scene.dragFile(event);" ondrop="scene.dropFile(event);"></canvas>
<script id="vshader" type="x-shader/x-vertex">
#ifdef GL_ES
precision highp float;
#endif

uniform mat4 mMatrix;
uniform mat4 vpMatrix;

attribute vec3 position;
attribute vec2 uv;

varying vec2 texCoord;

void main() {
gl_Position = vpMatrix * mMatrix * vec4(position, 1.0);
texCoord = uv;
}
</script>
<script id="fshader" type="x-shader/x-fragment">
#ifdef GL_ES
precision highp float;
#endif

uniform sampler2D texture;

varying vec2 texCoord;

void main() {
gl_FragColor = texture2D(texture, texCoord);
}
</script>
<script type="text/javascript">
var scene;
var frame;
window.onload = function() {
frame = new Frame();
if(frame.enabled){
scene = new Scene(frame.context3d);
frame.drawFunc = function(context3d){scene.draw(context3d);}
frame.run(new Date());
}
}
</script>
</body>
<script type="text/javascript">
Screen = {
width:640,
height:480
};
//! カラー定義
function Color(r,g,b,a){
this.r = r;
this.g = g;
this.b = b;
this.a = a;
}
//! シェーダ
function Shader(context3d, vshaderSource, fshaderSource, attrNames, uniformNames){
this.vshader = null;
this.fshader = null;
this.program = null;
this.attributes = [];
this.uniforms = [];
// 頂点シェーダー
this.vshader = context3d.createShader(context3d.VERTEX_SHADER);
context3d.shaderSource(this.vshader, vshaderSource);
context3d.compileShader(this.vshader);
if(!context3d.getShaderParameter(this.vshader, context3d.COMPILE_STATUS)){
alert(context3d.getShaderInfoLog(this.vshader));
}
// フラグメントシェーダー
this.fshader = context3d.createShader(context3d.FRAGMENT_SHADER);
context3d.shaderSource(this.fshader, fshaderSource);
context3d.compileShader(this.fshader);
if(!context3d.getShaderParameter(this.fshader, context3d.COMPILE_STATUS)){
alert(context3d.getShaderInfoLog(this.fshader));
}

this.program = context3d.createProgram();
context3d.attachShader(this.program, this.vshader);
context3d.attachShader(this.program, this.fshader);

context3d.linkProgram(this.program);
if(!context3d.getProgramParameter(this.program, context3d.LINK_STATUS)){
alert(context3d.getProgramInfoLog(this.program));
}

for(var i = 0; i < attrNames.length; i++){
var attr = context3d.getAttribLocation(this.program, attrNames[i]);
this.attributes = this.attributes.concat(attr);
}

for(var i = 0; i < uniformNames.length; i++){
this.uniforms = this.uniforms.concat(context3d.getUniformLocation(this.program, uniformNames[i]));
}
}
//! ボックスデータを作る
function Box(context3d){
this.vbuffer = [];
this.ibuffer = null;
this.indexCount = 0;
this.initVertexBuffer(context3d);
this.initIndexBuffer(context3d);
}
Box.prototype.initVertexBuffer = function(context3d){
var position = [
[-1,-1,-1],
[ 1,-1,-1],
[-1,-1, 1],
[ 1,-1, 1],

[-1, 1,-1],
[ 1, 1,-1],
[-1, 1, 1],
[ 1, 1, 1],
];
var uv = [
[0,1],
[1,1],
[0,0],
[1,0]
];
// 頂点配列を組み立てる
var index = [[0,1,2,3],[0,1,4,5],[2,3,6,7],[0,2,4,6],[1,3,5,7],[4,5,6,7]];
var vertexPosition = [];
for(var i = 0; i < 6; i++){
for(var j = 0; j < 4; j++){
vertexPosition = vertexPosition.concat(position[index[i][j]]);
}
}
var vertexTexCoord = [];
for(var i = 0; i < 6; i++){
for(var j = 0; j < 4; j++){
vertexTexCoord = vertexTexCoord.concat(uv[j]);
}
}
// Buffer作成
var vbuffer = context3d.createBuffer();
context3d.bindBuffer(context3d.ARRAY_BUFFER, vbuffer);
context3d.bufferData(context3d.ARRAY_BUFFER, new Float32Array(vertexPosition), context3d.STATIC_DRAW);
vbuffer.itemSize = 3;
this.vbuffer = this.vbuffer.concat(vbuffer);

vbuffer = context3d.createBuffer();
context3d.bindBuffer(context3d.ARRAY_BUFFER, vbuffer);
context3d.bufferData(context3d.ARRAY_BUFFER, new Float32Array(vertexTexCoord), context3d.STATIC_DRAW);
vbuffer.itemSize = 2;
this.vbuffer = this.vbuffer.concat(vbuffer);

context3d.bindBuffer(context3d.ARRAY_BUFFER, null);
}
Box.prototype.initIndexBuffer = function(context3d){
var index = [];
var base = 0;
for(var i = 0 ; i < 6 ; i++) {
index = index.concat(base + 0);
index = index.concat(base + 1);
index = index.concat(base + 2);
index = index.concat(base + 2);
index = index.concat(base + 1);
index = index.concat(base + 3);
base += 4;
}
// バッファを作成
this.ibuffer = context3d.createBuffer(context3d);
context3d.bindBuffer(context3d.ELEMENT_ARRAY_BUFFER, this.ibuffer);
context3d.bufferData(context3d.ELEMENT_ARRAY_BUFFER, new Int16Array(index), context3d.STATIC_DRAW);
context3d.bindBuffer(context3d.ELEMENT_ARRAY_BUFFER, null);
this.indexCount = index.length;
}
Box.prototype.draw = function(context3d, shader){
context3d.enableVertexAttribArray(shader.attributes[0]);
context3d.bindBuffer(context3d.ARRAY_BUFFER, this.vbuffer[0]);
context3d.vertexAttribPointer(shader.attributes[0], this.vbuffer[0].itemSize, context3d.FLOAT, false, 0, 0);
context3d.enableVertexAttribArray(shader.attributes[1]);
context3d.bindBuffer(context3d.ARRAY_BUFFER, this.vbuffer[1]);
context3d.vertexAttribPointer(shader.attributes[1], this.vbuffer[1].itemSize, context3d.FLOAT, false, 0, 0);
context3d.bindBuffer(context3d.ELEMENT_ARRAY_BUFFER, this.ibuffer);
context3d.drawElements(context3d.TRIANGLES, this.indexCount, context3d.UNSIGNED_SHORT, 0);
}

//! 描画シーン
function Scene(context3d){
this.updateTexture = false;
this.image = null;
this.texture = this.createEmptyTexture(context3d);
this.shader = new Shader(
context3d,
window.document.getElementById("vshader").text,
window.document.getElementById("fshader").text,
["position", "uv"],
["mMatrix", "vpMatrix"]);
this.box = new Box(context3d);
this.viewMatrix = mat4.create();
mat4.identity(this.viewMatrix);
mat4.translate(this.viewMatrix, [0, 0, -8]);
this.projectionMatrix = mat4.create();
mat4.identity(this.projectionMatrix);
mat4.perspective(30, Screen.width / Screen.height, 0.1, 1000, this.projectionMatrix);

this.count = 0;
}
Scene.prototype.draw = function(context3d){
this.count++;
if(this.updateTexture){
this.updateTexture = false;
this.texture = this.createTexture(context3d, this.image);
}
context3d.disable(context3d.CULL_FACE);
context3d.useProgram(this.shader.program);
var matrix = mat4.create();
mat4.identity(matrix);
mat4.rotate(matrix, 10 * this.count * Math.PI / 180, [0, 1, 0]);

var camMatrix = mat4.create(this.projectionMatrix);
mat4.multiply(camMatrix, this.viewMatrix);

context3d.uniformMatrix4fv(this.shader.uniforms[0], false, matrix);
context3d.uniformMatrix4fv(this.shader.uniforms[1], false, camMatrix);

context3d.bindTexture(context3d.TEXTURE_2D, this.texture);
context3d.texParameteri(context3d.TEXTURE_2D, context3d.TEXTURE_MAG_FILTER, context3d.LINEAR);
context3d.texParameteri(context3d.TEXTURE_2D, context3d.TEXTURE_MIN_FILTER, context3d.LINEAR_MIPMAP_LINEAR);
context3d.texParameteri(context3d.TEXTURE_2D, context3d.TEXTURE_WRAP_S, context3d.CLAMP_TO_EDGE);
context3d.texParameteri(context3d.TEXTURE_2D, context3d.TEXTURE_WRAP_T, context3d.CLAMP_TO_EDGE);

this.box.draw(context3d, this.shader);
}
Scene.prototype.dragFile = function(event){
if (event.dataTransfer.types[0] == "Files"){
event.preventDefault();
}
}
Scene.prototype.dropFile = function(event){
var file = event.dataTransfer.files[0];
if(file.type.match(/image\/\w+/)){
var reader = new FileReader();
reader.filename = event.dataTransfer.files[0].fileName;
var _this = this;
// エンコード完了後のコールバック
reader.onloadend = function() {
_this.setupImage(reader);
}
// Base64URI変換
reader.readAsDataURL(file);
}
}
Scene.prototype.setupImage = function(reader){
if(reader.error){
return;
}
this.image = new Image();
this.image.src = reader.result;
this.image = this.checkSize(this.image);
this.updateTexture = true;
}
Scene.prototype.createEmptyTexture = function(context3d){
var canvas = document.createElement('canvas');
canvas.height = canvas.width = 8;
var context = canvas.getContext('2d');
context.fillStyle = "#ffffff";
context.fillRect(0, 0, canvas.width, canvas.height);

return this.createTexture(context3d, canvas);
}
Scene.prototype.createTexture = function(context3d, image){
var texture = context3d.createTexture();
context3d.bindTexture(context3d.TEXTURE_2D, texture);
context3d.texImage2D(context3d.TEXTURE_2D, 0, context3d.RGBA, context3d.RGBA, context3d.UNSIGNED_BYTE, image);
context3d.generateMipmap(context3d.TEXTURE_2D);
context3d.bindTexture(context3d.TEXTURE_2D, null);
return texture;
}
Scene.prototype.checkSize = function(image) {
var w = image.naturalWidth;
var h = image.naturalHeight;
var size = Math.pow(2, Math.log(Math.min(w, h)) / Math.LN2 | 0);
if (w !== h || w !== size) {
var canvas = document.createElement('canvas');
canvas.height = canvas.width = size;
canvas.getContext('2d').drawImage(image, 0, 0, w, h, 0, 0, size, size);
image = canvas;
}
return image;
}
//! フレーム管理クラス
function Frame(){
this.enabled = false;
// コンテキストの準備
this.canvas = window.document.getElementById("canvas");
var contextName = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"];
for(var i = 0; i < contextName.length; i++){
try{
this.context3d = this.canvas.getContext(contextName[i]);
}catch(e){
}
if(this.context3d){
break;
}
}
if(!this.context3d){
return;
}
this.canvas.width = Screen.width;
this.canvas.height = Screen.height;
this.context3d.viewport(0, 0, Screen.width, Screen.height);
this.context3d.enable(this.context3d.TEXTURE_2D);
this.clearColor = new Color(0.1,0.1,0.1,1);
this.clearDepth = 1000;
this.enabled = true;
this.drawFunc = null;
}
Frame.prototype.clear = function(){
var cc = this.clearColor;
this.context3d.clearColor(cc.r, cc.g, cc.b, cc.a);
this.context3d.clearDepth(this.clearDepth);
this.context3d.clear(this.context3d.COLOR_BUFFER_BIT | this.context3d.DEPTH_BUFFER_BIT);
}
Frame.prototype.run = function(lastTime){
// クリア
this.clear();
this.context3d.enable(this.context3d.DEPTH_TEST);
this.drawFunc(this.context3d);
this.context3d.flush();
//! 更新を行う
var nowTime = new Date();
// 20FPS
var nextTime = 50 - (nowTime.getTime() - lastTime.getTime());
if(nextTime <= 0){
nextTime = 1;
}
var _this = this;
setTimeout(function(){_this.run(nowTime);}, nextTime);
}
</script>
</html>
posted by 管理人 at 16:33 | プログラミング