JavaScriptの3Dライブラリ three.js を試してみる

JavaScriptで3Dが描けるライブラリ three.js を試してみた。

three.js
https://github.com/mrdoob/three.js/

<!DOCTYPE html>
<html>
<head>
<title>three.js</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript" src="https://raw.github.com/mrdoob/three.js/master/build/Three.js"></script>
</head>
<body>

<script type="text/javascript">
$(function(){
  var width = 800;
  var height = 500;
  function init(){

    var camera = new THREE.Camera(75, width / height , 1, 10000);
    camera.position.z = 1000;

    var scene = new THREE.Scene();

    var geometry = new THREE.CubeGeometry(200, 200, 200);
    var material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: false } );

    var mesh = new THREE.Mesh(geometry, material);
    scene.addObject(mesh);

    var renderer = new THREE.CanvasRenderer();
    renderer.setSize(width, height);

    $('#three').append(renderer.domElement);

    mesh.rotation.x = 0.8;
    mesh.rotation.y = 0.3;
    mesh.rotation.z = 0.3;
    renderer.render(scene, camera);

  }
  init();
});
</script>

<div id="three"></div>

</body>
</html>

mesh.rotation の x, y, z をいじれば視点が変わるようだ。

Scalaの限定継続のshiftだけを含む関数オブジェクトを作れるかを実験

関数オブジェクトの定義の中にshiftを入れて、関数オブジェクトを別のメソッドに渡す、そのメソッドではresetの中でその関数オブジェクトを呼び出す、ってのができるかを実験した。

import scala.util.continuations.cpsParam;
import scala.util.continuations.reset;
import scala.util.continuations.shift;

object test {

  def main(args: Array[String]){

    val f: Int => Long @cpsParam[String, (String, String)] = {
      a: Int =>
      shift { ctx: (Long => String) =>
        val s = ctx(a * 10000L);
        (s, "test:f");
      }
    }

    val g: Int => Long @cpsParam[String, (String, String)] = {
      a: Int =>
      shift { ctx: (Long => String) =>
        val s = ctx(a * 20000L);
        (s, "test:g");
      }
    }

    sub(f);
    sub(g);

  }

  private def sub(f: Int => Long @cpsParam[String, (String, String)]){

    val result: (String, String) = reset {
      val a: Int = 123;
      val b: Long = f(a);
      (a + b).toString;
    }

    println(result);

  }

}
$ scalac -P:continuations:enable test.scala && scala test
(1230123,test:f)
(2460123,test:g)

作れるみたい。

REPLで限定継続を試すには、コンパイラのオプションと同様に

$ scala -P:continuations:enable

とする必要がある模様。

$ scala
Welcome to Scala version 2.9.0.1 (OpenJDK 64-Bit Server VM, Java 1.6.0_20).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import scala.util.continuations._;
import scala.util.continuations._

scala> val f = { a: Int => shift { ctx: (Long => String) => val s = ctx(a * 10000L); (s, "test:f"); } }
<console>:10: error: this code must be compiled with the Scala continuations plugin enabled
       val f = { a: Int => shift { ctx: (Long => String) => val s = ctx(a * 10000L); (s, "test:f"); } }
                                 ^

scala> :quit
$ scala -P:continuations:enable
Welcome to Scala version 2.9.0.1 (OpenJDK 64-Bit Server VM, Java 1.6.0_20).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import scala.util.continuations._;
import scala.util.continuations._

scala> val f = { a: Int => shift { ctx: (Long => String) => val s = ctx(a * 10000L); (s, "test:f"); } }
f: (Int) => Long @scala.util.continuations.cpsParam[String,(String, java.lang.String)] = <function1>

scala> f(3)
None/None/Some((String,(String, java.lang.String)))
<console>:12: error: found cps expression in non-cps position
       f(3)
        ^

scala> reset { f(3).toString; }
res1: (String, java.lang.String) = (30000,test:f)

gitのインデックスにローカルで変更があったファイルも削除されたファイルもすべてまとめて反映する方法

追加したファイルや変更のあったファイルや削除したファイルがたくさんあるが、全部をインデックスに反映しようと思って

git add .

としても、削除したファイルはインデックスに反映されない。

削除ファイルを個別に git rm するのはめんどいので、

git add -A

とするとよい。
これで、追加も変更も削除もすべてローカルからインデックスに登録される。

scalaの限定継続 その2

限定継続をいろいろ実験中。

if文や try/catch の中に shift を置く場合、どの分岐経路を通っても、ifやtryの戻り値型に同じ cpsParam のアノテーションが付くようにしなければいけない。

この例では、tryの中に shift を置いた例。try中のshiftは戻り値型が @cpsParam[String, String] なので、catchも @cpsParam[String, String] になるように shift を置かないといけない。

import scala.util.continuations._;

object Demo2 {

  def main(args: Array[String]){

    val result = reset {

      // (1)

      try {

        val b = shift { ctx: (String=>String) =>
          // (2)
          val c1 = ctx("abc");
          // (7) c1 = "ERROR"
          val c2 = ctx("ABC");
          // (11) c2 = "ABCdef"
          c1 + ":" + c2; // (12) return "ERROR:ABCdef"
        }

        // (3) b = "abc"
        // (8) b = "ABC"

        if(b == "abc"){
          // (4)
          throw new Exception();
        }

        // (9)
        b + "def"; // (10) return "ABCdef"

      } catch { case e =>
        // (5)
        shift { ctx: (String=>String) =>
          // (6)
          "ERROR";
        }
      }

    }

    // (13) result = "ERROR:ABCdef"

    println(result);

  }

}

コメントの中の番号は、実行される順序で、番号の右にその時の変数の値などを示す。tryの中のshiftでctxを2回呼び出しているので、(3)(8)の箇所は2回通過する。1回目はその下のif文にマッチしcatchブロックに進み、2回目はif分にマッチせずに次に進む。

catchの中にもshiftを書かないといけないのはスマートじゃない気がするが、こんなことしないといけないのか。他に方法はないのか。

初めてのscala限定継続

↓この記事を読んでやっと限定継続が理解できた。
http://d.hatena.ne.jp/shomah4a/20110113/1294934879

この理解をもとに初めて書いた限定継続のコード。

import scala.util.continuations._;

object Demo {

  def main(args: Array[String]){

    // (1)

    val result = reset {

      // (2)

      val a = shift { ctx: (String=>String) =>
        // (3)
        ctx("abc");
        // (9) return "abc12"
      }

      // (4) a = "abc"

      val b = shift { ctx: (String=>Int) =>
        // (5)
        a + ctx(a + "def");
        // (8) return "abc12"
      }

      // (6) b = "abcdef"

      b.length * 2; // (7) return 12

    }

    // (10) result = "abc12"

    println(result);

  }

}

コンパイル

scalac -P:continuations:enable continuations.scala

とする。

reset の中に shift を複数置けることを確認したかったが、結論としてはできるようだ。

コメントの中の番号は、実行される順序で、番号の右にその時の変数の値などを示す。

1つ目の shift の ctx の戻り値が String なのは、shift の後のコードの実行結果が String だからで、それは (7) の Int ではなく、2つ目の shift のブロックの戻り値 (8) が String だからだ。2つ目の shift の ctx の戻り値が Int なのは、(7) が Int だからだ。

sshfsの使い方

Ubuntuにインストールするには、

$ sudo apt-get install sshfs

マウントするには、

$ sshfs -p ポート番号 ユーザ名@ホスト:リモートディレクトリ マウント先ディレクトリ

ポート番号が普通の22番なら -p オプションはいらない。

アンマウントするには、

$ fusermount -u マウント先ディレクトリ

とする。

wgetの使い方メモ

ウェブサイトのダウンロード

第3階層までリンクをたどりまるごとダウンロードする

wget -r -l3 URL

-l を指定しないと、デフォルトで -l5。


ウェブサイトを第5階層までリンクをたどりまるごとダウンロードする。かつローカルでサイトを閲覧できるように、パスを相対パスに書き換え、拡張子をhtmlにする。

wget -r -l5 --convert-links --html-extension URL

ファイルを書き換える際にオリジナルファイルをバックアップとして残しておく。

wget -r -l5 --convert-links --html-extension --backup-converted URL


BASIC認証をしていするには以下のオプションを付ける。

--http-user=ユーザー名
--http-passwd=パスワード

うるおぼえだがバージョン 1.12 ぐらいからはCSSから参照される画像などもダウンロードしてくれるようになっている。

FTPでまるごとダウンロード

wget -r ftp://username:password@host/path

GNU Wget 1.12 Manual
http://www.gnu.org/software/wget/manual/wget.html

GNU Wget 1.9 Manual
http://www.bookshelf.jp/texi/wget/wget-ja.html
(日本語訳だが古いバージョン)