初めての WebGL

ここ 1年くらいのブログを見返しているとずいぶん投稿数が減ったなぁ、と。 こうみえて昔は、毎日更新だったんですよ(笑) 原因は何かの途中経過を書かなくなったことだと思うのですが、それは新しいことをやっていない裏返しなのかも、ということで「初めての WebGL」。。

まずはお勉強でございます。 ちなみにわたくしは、3D とか全然分からないです(笑)

WebGL Lesson 1 – 三角形と四角形 – Hack The WebGL (WebGL勉強会)

ようこそ私の最初のWebGLチュートリアルへ!この最初のレッスンはNeHe OpenGLチュートリアルのNo.2をもとにしています。NeHe OpenGLチュートリアルはゲーム開発者向けの3Dグラフィックスの学習手段として人気です。
今回はWebページ上に三角形と四角形を出す方法を解説します。

大変参考になりますです。

まず分かったのは、WebGL は OpenGL 2.0 ES のラッパーであって OpenGL とは互換がないということです。 以前、ちょっと OpenGL をいじっていたのでそのまま移植できるかなと思ってたのですが、いわゆる固定シェーダがないのですね。

hiromasa.another :o)» Blog Archive » Java + LWJGL + OpenGL で 2D ゲーム

ということでとりだしてきました、 OpenGL の Java ラッパー LWJGL。 OpenGL で古き良き 2D 描画をなんとか再現してやろうかと奮闘中であります。

2.0 ES でレンダリングするには必ずバーテックスシェーダとフラグメントシェーダで描画する必要があるようです。 JavaScript の中に C like な記述が入るのはなかなか興味深い。

webgl01

というわけでいろいろふっとばしますが、なんとか豆腐とテクスチャの貼り付けまではいけました。 ソースはもうちょっと動いてからにしましょう。

 

オチなしのプレッシャー…。

Firefox 4.0 リリース!

結構前から Minefiled で beta を追っていていたのですが beta13 から RC1、2 を経ましてついに Firefox 4.0 がリリースされました。 🙂 1.0 がでて喜んでいたのは 2005 年ですので月日が流れるのは早いものです。。

4.0 で最初にぱっと目を引くのは UI の変更で、Tab on Top とかメニューが左上に統合されたり、タブをピンで止めれるようになったりしています。

Linux 版。

firefox402

Windows 版。

firefox401

 

Windows のほうの beta はあまり見ていなかったのですが、途中でタブのデザインが変わったように思います。 正式版いれたときあれ?って思いました。 🙂

Ubuntu 10.10 は Firefox 3.5 系なので 4.0 を使うには stable の PPA を入れると良いと思います。

Nattyまで待てない!Ubuntuで今すぐFirefox4.0を使う

さて、我らがUbuntuでは、現行版の10.10Maverickでは残念ながらアップデートが入ってきていません。せっかく高速に便利になったFirefox 4.0が使えないのはもったいないので、10.10でもFirefox 4.0を使えるようにしました。

非常に参考になります!

何度かこのブログでも取り上げていました、新機能の WebGL についてですが、Linux 版については残念ながら NVIDIA プロプライエタリ ドライバ以外はブラックリスト入りの対応になったようです。

しかるに NVIDIA 以外のカードではいじらずには WebGL 表示できません。 無念。 beta の途中までは Intel とかでも動いていたのですが、バグが多かった模様です。

Windows に関しては Intel 内蔵とかでも動くようなので遊んでみると良いかもしれません。

WebGL Experiments

WebGL is a new web technology that brings hardware-accelerated 3D graphics to the browser without installing additional software.To try these WebGL experiments with Google Chrome, please download and install it below.

基本 Chrome デモ用ですがこちらのサイトに続々新作が追加されています。

firefox403

少しインターネットを検索していると、初音ミクさんが踊りだしたりしていました。 面白いのができる予感。 ぼくも空間系のサイトを何かやってみたいなと思っているのですが、OpenGL 勉強しないとですね。

…。 やべっ。

無理矢理のオチ。。。 (IE8 ではでませんな

Groovy と PS3 Media Server プラグイン

主に PS3 向けの DNLA サーバアプリ PS3 Media Server のプラグインを、言語の勉強がてら Groovy でかいてみました。 🙂

また、pms のプラグインのつくりかたはあまりインターネット上にドキュメントがないみたいなのでメモも兼ねまして。 まぁこんなことしようする人はソースみれば分かる内容ですが(笑)。。。

PS3 Media Server は Java でできていますので、Groovy の jar をクラスパスにいれてあげれば Groovy でプラグインをかくことができます。 Groovy 言語はプリコンパイルでただの .class にできますので Java との相互運用性は非常に高く、こういうときにとても便利です。

とりあえず、pms3 の trunk を落としてきて lib/groovy-all-1.7.10.jar を入れて、ant かけて pms3.jar の本体を差し替え。 あとはプラグインかくだけ。

以下ソースから追ってつくっていますので、間違えがありましたらご容赦を。

まず作成するプラグインを以下のパッケージに配置。

package net.pms.external

 

画面にルートフォルダを一つ追加する場合は、AdditionalFolderAtRoot を implements してあげたクラスを作成。 で、extends VirtualFolder なクラスをつくって addChild して構築したものを getChild() から戻してあげれば初期設定完了です。

class SamplePlugin implements AdditionalFolderAtRoot {
    
    def root
    
    def SamplePlugin() {
        root = new VirtualFolder("Sample", "")
        root.addChild(new SampleDirectory("Child"))
    }
    
    @Override
    public DLNAResource getChild() {
        return root
    }
    
    @Override
    public String name() {
        return "SamplePlugin"
    }
    
    @Override
    public void shutdown() {
        // nothing to do
    }
    
    @Override
    public JComponent config() {
        // no gui
        return new JPanel()
    }
}

 

extends VirtualFolder な discoverChildren() ではそれが持つ子供(さらにフォルダとかファイルとかストリームとか)を addChild(DLNAResiyrce) で追加していきます。このメソッドはクリックされたときに動きます。

class SampleDirectory extends VirtualFolder {
    
    def SampleDirectory(name) {
        super(name, "")
    }
    
    @Override
    public void discoverChildren() {
        addChild(new SampleDirectory("Child"))
        addChild(new WebAudioStream("Station", "http://127.0.0.1/", ""))
        addChild(new RealFile(new File("/tmp/hoge.mp3"))
    }
}

 

簡単あるね。 上のソースは今そらで書いたものなので動かなかったらすいません。。イメージということで。。

最後に plugin というテキストファイルに起動クラス名(この場合は net.pms.external.SamplePlugin)を記述した上で jar にして pms3 の plugins フォルダに格納してサーバ起動すれば動作するはずです。

 icecast_02

trunk 版の起動シェルはプラグインディレクトリにクラスパス通さなくなっている修正がかかっていますのでそちらも併せて。起動メッセージに Found Plugin がでれば成功。 (ちなみに newInstance() しているのは net.pms.external.ExternalFactory.java です。 うまくプラグインが読まれない場合は確認を)

icecast_01

てなわけで、こちらは動作する例ということで Icecast サーバの実装が出力する yp.xml を解析して PS3 上に表示して再生するプラグインです。 ジャンルでサマってフォルダ分けしています。

package net.pms.external
 
import javax.swing.JPanel
import javax.swing.JComponent
 
import net.pms.dlna.DLNAResource
import net.pms.dlna.WebAudioStream
import net.pms.dlna.virtual.VirtualFolder
 
class IcecastPlugin implements AdditionalFolderAtRoot {
    
    def root
    def icecast
    
    def IcecastPlugin() {
        icecast = new Icecast("http://www.example.com/yp.xml")
        
        root = new IcecastDirectory("Icecast Radio", "", {})
        root.addChild(new IcecastDirectory("Genre", "", { c1 ->
            icecast.getGenre().each {
                c1.addChild(new IcecastDirectory(it, it, { c2 ->
                    icecast.getStationByGenre(c2.query).each {
                        c2.addChild(new WebAudioStream(it.value, it.key, ""))
                    }
                }))
            }
        }))
    }
    
    @Override
    public DLNAResource getChild() {
        return root
    }
    
    @Override
    public String name() {
        return "IcecastPlugin"
    }
    
    @Override
    public void shutdown() {
        // nothing to do
    }
    
    @Override
    public JComponent config() {
        // no gui
        return new JPanel()
    }
}
 
class IcecastDirectory extends VirtualFolder {
    
    def explorer
    def query
    
    def IcecastDirectory(name, query, explorer) {
        super(name, "")
        this.query = query
        this.explorer = explorer
    }
    
    @Override
    public void discoverChildren() {
        explorer(this)
    }
}
 
class Icecast {
    
    def yp
    def ypxml
    
    def Icecast(yp) {
        this.yp = yp
    }
    
    def getStationByGenre(genre) {
        parse()
        def stations = [:]
        ypxml.entry.each {
            if(it.genre.text() == genre) {
                stations[it.listen_url.text()] =
                    "${it.server_name.text()} (${it.bitrate.text()}K)"
            }
        }
        return stations
    }
    
    def getGenre() {
        parse()
        def genres = [:]
        ypxml.entry.each {
            genres[it.genre.text()] = ""
        }
        return genres*.key.sort()
    }
    
    def parse() {
        if(ypxml != null && ypxml.entry.size() != 0) return
        ypxml = new XmlParser().parse(yp)
    }
}

 

Groovy の勉強を兼ねていましたので中途半端に遊んでるソースですいません。 木構造でクロージャ渡しの遅延評価を使って一度にツリーを構築しています。 あとは  XML の解析部分が Groovy っぽい部分でしょうか。 ぼくが分からないだけでもっと良い方法はあることでしょう!

さて、こんな感じのものを Java でかいていたらさすがにぼくでもいらっとしそうですが、Groovy なら気楽に短時間でかけますね。

これは動かして調整して、、たぶん…。

[tegaki]このブログ書く方が時間かかっている![/tegaki]

完。