世界を変態で埋め尽くせ!!

変態アドベントカレンダー5日目担当のはがねのつるぎです。
昨日は@kuchitamaさんのでした「Vimを変態にしてみた」でした。

three.jsを使って3D空間に変態を敷き詰めていこうと思います。

3Dプログラミングは色々と手順があります。まずは、レンダラーとシーンを設定して変態空間を作ります。レンダラーとは世界の描き方のこと。変態空間がどのようにみえるか?を決定します。たとえるなら生物でいう眼の構造みたいなものでしょうか。せっかくなのでWebGLを使ってみます。

// レンダラー
var renderer = new THREE.WebGLRenderer({ antialias:true });
// 画像サイズ
renderer.setSize(500 , 500);
renderer.setClearColorHex(0x000000, 1);
// DOMに追加
document.body.appendChild(renderer.domElement);

シーンは世界そのものです。このシーンにオブジェクトを追加して変態化を進めていきます。

// シーン
var scene = new THREE.Scene();

まだ変態空間があっても見るすべがありません。
変態と言えば覗きですね。カメラを作ります。

// カメラ
var camera = new THREE.PerspectiveCamera(70, 500 / 500);
// カメラの座標
camera.position = new THREE.Vector3(0, 0, 1);
// カメラターゲット
camera.lookAt(new THREE.Vector3(0, 0, 0));
scene.add(camera);

まだ変態空間は暗闇に包まれています。変態に光あれ。

// ライト
var light = new THREE.DirectionalLight(0xcccccc);
// ライト座標
light.position = new THREE.Vector3(0.577, 0.577, 0.577);
scene.add(light);
// 環境光
var ambient = new THREE.AmbientLight(0x333333);
scene.add(ambient);

ここからが本編です。
変態を敷き詰めるためにパーティクルシステムを使います。
パーティクルシステムはCGでよくある爆発や煙なんかを表現するのに便利な技術です。

まずは、コアとなるオブジェクトと変態を出現させる座標をランダムで作っていきます。


// 形状データを作成
var geometry = new THREE.Geometry();
var numParticles = 500;
for(var i = 0 ; i < numParticles ; i++) { // 座標をセット geometry.vertices.push(new THREE.Vector3( Math.random() * 2000 - 1000, Math.random() * 2000 - 1000, Math.random() * 2000 - 1000)); } [/javascript] 座標に割り当てる変態を作成します。 [javascript] // マテリアルを作成 var texture =THREE.ImageUtils.loadTexture('hentai.png'); var material = new THREE.ParticleBasicMaterial({ size: 200, color: 0xffffff, blending: THREE.AdditiveBlending, transparent: false, depthTest: false, map: texture }); [/javascript] パーティクルを使って変態を出現させます。 [javascript] // 物体を作成 var mesh = new THREE.ParticleSystem(geometry, material); mesh.position = new THREE.Vector3(0, 0, -1200); mesh.sortParticles = true; scene.add(mesh); [/javascript] 実行すると変態空間の完成です。 変態空間

ここまでで、変態空間は完成ですがせっかくなので動かしてみました。
初期化が大変みたいでChromeでも、あんまりまともに動きません。

デモ ※Chrome推奨

最先端すぎてブラウザでさえついてこれないのがはがねクオリティーです。

明日は@ponkoreさんです。よろしくお願いします。

[RESTeasy]JSONのアンマーシャルと文字判定

RESTeasyでJSONをUnmarshalしようとするとして文字化けが起こりパースに失敗する。

RESTeasyではデフォルトでJSONのマーシャル、アンマーシャルにはjettisonを使っている。
jettisonには問題なさそうなのでで、RESTeasyからjettisonに渡す配管コードを追いかけてみた。

JettisonMappedUnmarshallerクラスがjettisonのunmarshallerに投げているのだが、これがよろしくないようだ。

public Object unmarshal(Source source)
        throws JAXBException {
    if (!(source instanceof StreamSource)) {
        throw new UnsupportedOperationException("Expecting a StreamSource");
    }
    StreamSource stream = (StreamSource) source;
    XMLStreamReader reader = getXmlStreamReader(new InputStreamReader(stream.getInputStream()));
    return unmarshal(reader);
}

InputStreamをReaderに食べさせているのだが、文字コードの指定がない。

InputStreamReaderのコンストラクタは第二引数の文字コードの指定が省略された場合にStreamDecoder.forInputStreamReader()を使い文字コードを決定する。この、文字コードの判定がVM引数の”file.encoding”をみている。”file.encoding”はWindows系だとMS932とか使われる場合がある。つまり、OSに依存するって話だ。

もちろん、Tomcatなりglassfishなりで起動オプションで指定すればいいのだが、RESTのとあるデータ形式からのアンマーシャルで使っていいような環境変数ではない気がする。

ここは、リクエストのContent-Typeからひっぱてくるか、InputStreamを解析して文字コードを取得するかどっちかだと思う。

AjaxSliderのバグ

WicketとjQueryの連携にwiQueryを使ってスライダーを使いたい。

AjaxSliderクラスを継承。スライダーのつまみを掴んだ瞬間、startイベントでサーバサイドにイベントを通知して、アトはslideイベントにバインドして、つまみを掴んでいる間は、jQueryで処理というクラスを作ってみた。

使用したバージョンはwiQuery1.5.0 wicketは1.5.2

ちなみに、wiQueryではsetter系メソッドでいろいろと処理が動いているので
getter系メソッドでオーバーライドとかしないようにしている。

public class HogeSlider extends AjaxSlider {

  public HogeSlider(String id, Number min, Number max) {
    super(id, min, max);
  }

  @Override
  protected void onInitialize() {
    super.onInitialize();

    // スライド中のイベント
    setSlideEvent(new JsScopeUiEvent() {

      @Override
      protected void execute(JsScopeContext scopeContext) {
        // あとからsetAjaxStartEvent()を登録すると無効になる。
        scopeContext.append("console.log('slide now');");
      }
    });

    // スライド開始時にAjax通信する
    setAjaxStartEvent(new ISliderAjaxEvent() {

      @Override
      public void onEvent(AjaxRequestTarget target, AjaxSlider slider, int value, int[] values) {
        System.out.println("ajax start event!!");
      }
    });
  }
}

が、イベントが思うように動作しない。

しょっちゅうサーバサイドと通信が走るし、console.logには何も出力されなくなりsetSlideEvent()の処理が動かない。ようするに使えない。

setAjaxStartEvent()をコメントアウトすると、正常に’slide now’という文字が出力される。
悪さをしているのはsetAjaxStartEvent()で間違いない。

AjaxSliderクラスを確認する。

  public void setAjaxStartEvent(ISliderAjaxEvent ajaxStartEvent)
  {
    this.ajaxEvents.put(SliderAjaxEvent.ajaxStartEvent, ajaxStartEvent);
    setSlideEvent(new SliderAjaxJsScopeUiEvent(this, SliderAjaxEvent.ajaxStartEvent));
  }

はい、ビンゴ!

slideイベントに登録されてる。本来ならstartイベントであるはずだ。

ついでに、AjaxSliderクラスの親クラスであるSliderクラスのsetSlideEvent()も調査。

  public Slider setSlideEvent(JsScopeUiEvent slide)
  {
    this.options.put("slide", slide);
    return this;
  }

this.options.put()しているのはただのMapなのでイベントは上書きされて、最初にsetSlideEvent()で登録したイベントは無効になる。これで現象は全部つかめた。

イベントの上書きは、とりあえず妥協してもいいだろう。しかし、バインドするイベントは間違えては困る。スコープの関係でAjaxSliderクラスそのものを修正しなければならない。

  public void setAjaxStartEvent(ISliderAjaxEvent ajaxStartEvent)
  {
    this.ajaxEvents.put(SliderAjaxEvent.ajaxStartEvent, ajaxStartEvent);
    //setSlideEvent(new SliderAjaxJsScopeUiEvent(this, SliderAjaxEvent.ajaxStartEvent));
    setStartEvent(new SliderAjaxJsScopeUiEvent(this, SliderAjaxEvent.ajaxStartEvent));
  }

として再コンパイルすれば期待通りの動作となる。

ITコミュニティ夏祭り

カルカルのスライドをアップしました。

前半のまじめな部分って2,3枚ぐらいで十分だったような気がするし
継承の話以外は全部省略してよかった気がする。

ちょっとづつ暴走……みたいにやってみたい。
LTヘタだなぁと思い反省。

関連リンク
http://el.jibun.atmarkit.co.jp/topics/2011/08/it-474f.html
http://tcc.nifty.com/cs/catalog/tcc_schedule/catalog_110816203681_1.htm
http://www.ustream.tv/recorded/17324450
http://www.ustream.tv/recorded/17326509
http://togetter.com/li/189266

コラムニストとして情報発信をするということ

OSC京都2011 もうひとつのセミナー(?) LT大会の資料&UST

USTは13分ちょっとすぎたあたり

jQueryプラグインの「使い方」ではなく「作り方」

OSC京都の セミナー資料とデモとUST

デモ IEでは動きません(TT)
プラグイン
UST

jQueryの空判定

jQueryのソースを眺めていたら、オブジェクトの空判定をするコードを見つけた。

isEmptyObject: function( obj ) {
  for ( var name in obj ) {
    return false;
  }
  return true;
},

普通ならnullチェックをするような処理である。しかし、javascriptにはnull以外にもundefinedという未定義値が存在する。これらを一個づつチェックしていく方法ももちろん正しい。

javascriptのfor/in文は、オブジェクトのプロパティごとにループを回す。プロパティが存在すればループ内部が実行し、falseを返す。オブジェクトが空の場合、プロパティが存在しないのでforループそのものが実行されず trueが返される。

仮にループが実行されたとしても、ループ内処理は、たった一回しか実行されない。この文脈においてfor/in文はif文と同じ役割を果たしているのだ。

査読論文を提出してきた

全125ページ。読めるものな読んでみやがれってんだ(^^)

ダメ出しもあるだろうし発表資料とか作らなくちゃいけないんだけど、一区切りついたような気がする。2年前と比べて何か変わったのだろうか。ちゃんと真摯に向き合えただろうか。ちゃんとレベルアップできたのだろうか。

こういう一区切りついた瞬間は何もかもが真っ白になる。気持ちににムラッ気があるのは悪いクセだ。もうひと踏ん張り、残り一ヶ月がんばる。

自分の知らない言葉は検索できない

デジタルな世界は能動的に動くことを是とする。受身で情報収集していてるのならアナログな世界で情報を得ることと変わらないない。yahooニュースでニュースを知ることと、朝のニュース番組でニュースを知ることにそんなに違いはない。

インターネットで、わからない言葉に出会ったときに瞬時に検索できるって言うよね。だけど、よくよく考えればニュース番組だって丁寧に解説してくれているじゃないか。

本屋さんで何気なくとった本が世界を広げてくれる。そんな感覚をネットの世界に持ち込んだのがtwitterなりMIXIなりの友達がしゃべった言葉だ。

デジタルな検索の世界には偶然の出会い、セレンディピティがない。もちろん、そこに挑戦する動きも当然のごとくある。twitterの中から重要っぽい言葉を重み付けして、自分の発言を係数にしたら、みたいなアルゴリズムを考えるのが次世代検索エンジンなんだろう。

検索のインプットが単なる単語、キーワードでは足りなくなった。人が面白いと思う感覚は千差万別だ。「面白い画像」に対する検索結果がすべての人にとって同じ結果ではなくて、わたしだけの結果であること。自分の発言やネット上での行動から文脈、コンテキストをキーにする。そういう検索方法っていうのが今後生まれてくる。

そんな検索エンジンが実現できたとして……

そこで自分も知らない結果が突きつけられたら?
自分でも気づかなかった新しい「面白い画像」であればいい。例えば、とんでもなく猟奇的な画像を「面白い画像」の検索結果として突きつけられたらどうなるだろう。

技術は使い方である。コンテキスト検索が自分自身の持つ闇の感情やネガティブな思想を呼び起こすプログラムだとしたら、その結果を直視できるだろうか。

ソーシャル・ネットワーク

マーク・ザッカーバーグは「世界で最も若い10人の億万長者」のひとりである。「ソーシャルネットワーク」は彼が大学時代に作ったWebアプリケーション「facebook」とそれにまつわる物語だ。

彼の在籍するハーバード大学限定で始まった「facebook」は瞬く間にキャンパスを席巻。少しづつサービスを拡大し数年で5億人が使うアプリケーションにまで成長した。世界人口が69億人。世界の14人にひとりが使っている計算である。

誰もが使いたがるソフトウェアは金のなる木だ。「facebook」が成長していく過程で買収の話は幾度となくあった。売れるソフトウェアに買収の話はつきものである。いかに高値で大企業に買われるか?大学発のベンチャー企業が考えるゴールのひとつだ。

しかし、自分のチカラでゼロから生み出したソフトウェアはエンジニアにとって宝物である。会社ごと売り払って大金を手にするか、会社を存続させてソフトウェア開発を続けるか。2択を迫られる。10億ドルを突きつけられて平気な人間などいやしない。そういうギリギリの葛藤の世界だ。

この映画の面白いところは、主人公の行動原理がハッカー的な思考にもとづいていることにある。ビジネスマンであるよりもプログラマーであることに価値観を置く。さきほどの買収話もそのハッカー的思考にもとづいて判断をくだす。その考え方は共感を覚える。

いままでにいろんなビジネス書を読んできてしっくりとこない理由がわかった気がした。。ビジネスマン的思考はわたしのモノの考え方にそぐわない。自分の考え方はプログラマーのそれであり、エンジニア的思考のそれであり、ハッカー文化のそれである。立ち居地がそこにあること確認することができた。

「シンプルにやれ」

エンジニアはもっと自由であっていいんだと思う。