@blog.justoneplanet.info

日々勉強

XCodeでC言語を使って遊ぶ

Mac OS X ApplicationからCommand Line Toolを選択するととっつきやすい。

#include <stdio.h>

int main (int argc, const char * argv[])
{
    printf("こんにちは!\n%d円よこしてください", );
    return 0;
}
#include <stdio.h>

int main (int argc, const char * argv[])
{
    int cost = 100;
    printf("こんにちは!%d円よこしてください\n", cost);
    cost = 10000;
    printf("こんにちは!%d円よこしてください\n", cost);
    return 0;
}

■インクルードガード

main.c

#include <stdio.h>
#include "hoge.h"

int main (int argc, const char * argv[])
{
    printf("こんにちは!%d円よこしてください\n", hoge());
}

hoge.h

#ifndef INCLUDED_MAIN
#define INCLUDED_MAIN

int hoge();

#endif

hoge.c

#include "hoge.h"

int hoge()
{
    return 100;
}

android版かおもじ辞典をリリースしました

Simejiの拡張機能としてandroid版かおもじ辞典をリリースしましたʕ→ᴥ←ʔ キュンキュン!

■ダウンロード

こちらより無料でダウンロードできます。

■機能

マイ顔文字

登録してシェアすることができます。

みんなの顔文字

みんなが登録した顔文字を見ることができます。好きなモノをロングタップしてマイ顔文字に保存できます。

人気の顔文字

みんなが使ってる顔文字の人気ランキングです。知らない顔文字があったらロングタップして保存しましょう。

■Chrome版

こちらをご覧ください。

■iPhone版

こちらをご覧ください。

OpenGL ESメモ

コードを書いておく。ただそれだけ。

package info.justoneplanet.android.glsample;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Bitmap.Config;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.opengl.GLUtils;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.SurfaceView;

public class MainActivity extends Activity {
    private GLSurfaceView gLSurfaceView;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        gLSurfaceView = new GLSurfaceView(this);
        gLSurfaceView.setRenderer(new Renderer());
        setContentView(gLSurfaceView);
    }

    @Override
    public void onPause()
    {
        super.onPause();
        gLSurfaceView.onPause();
    }

    @Override
    public void onResume()
    {
        super.onResume();
        gLSurfaceView.onResume();
    }

    private class Renderer implements GLSurfaceView.Renderer
    {
        @Override
        public void onDrawFrame(GL10 gl) {
            gl.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

            // camera
            {
                gl.glMatrixMode(GL10.GL_PROJECTION);
                gl.glLoadIdentity();

                GLU.gluPerspective(gl, 45.0f, 1.0f, 0.01f, 100.0f);
                GLU.gluLookAt(gl, 0, 0, 10.0f, 0, 0, 0.0f, 0.0f, 1.0f, 0.0f);
            }

            // vertices
            {
                final float one = 1.0f;

                final float[] vertices = new float[]{
                         one,   one,   one,
                         one,   one,  -one,
                        -one,   one,   one,
                        -one,   one,  -one,
                         one,  -one,   one,
                         one,  -one,  -one,
                        -one,  -one,   one,
                        -one,  -one,  -one,
                };

                FloatBuffer fb = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();

                fb.put(vertices);
                fb.position(0);

                gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
                gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fb);
            }

            {
                gl.glMatrixMode(GL10.GL_MODELVIEW);
                gl.glRotatef(1.0f, 0, 1, 0);// 回転
            }

            {
                final byte[] indices = new byte[]{0, 1, 2, 3, 6, 7, 4, 5, 0, 1};
                ByteBuffer bb = ByteBuffer.allocateDirect(indices.length).order(ByteOrder.nativeOrder());
                bb.put(indices);
                bb.position(0);
                gl.glColor4f(0, 1, 0, 1);
                gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, bb.capacity(), GL10.GL_UNSIGNED_BYTE, bb);
            }

            {
                final byte[] indices = new byte[]{1, 5, 3, 7};
                ByteBuffer bb = ByteBuffer.allocateDirect(indices.length).order(ByteOrder.nativeOrder());
                bb.put(indices);
                bb.position(0);
                gl.glColor4f(0, 0, 1, 1);
                gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, bb.capacity(), GL10.GL_UNSIGNED_BYTE, bb);
            }

            {
                final byte[] indices = new byte[]{0, 2, 4, 6};
                ByteBuffer bb = ByteBuffer.allocateDirect(indices.length).order(ByteOrder.nativeOrder());
                bb.put(indices);
                bb.position(0);
                gl.glColor4f(1, 0, 0, 1);
                gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, bb.capacity(), GL10.GL_UNSIGNED_BYTE, bb);
            }
         }

        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            gl.glViewport(0, 0, width, height);
        }

        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
       }
    }
}
package info.justoneplanet.android.glsample;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Bitmap.Config;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.opengl.GLUtils;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.SurfaceView;

public class MainActivity extends Activity {
    private GLSurfaceView gLSurfaceView;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        gLSurfaceView = new GLSurfaceView(this);
        gLSurfaceView.setRenderer(new Renderer());
        setContentView(gLSurfaceView);
    }

    @Override
    public void onPause()
    {
        super.onPause();
        gLSurfaceView.onPause();
    }

    @Override
    public void onResume()
    {
        super.onResume();
        gLSurfaceView.onResume();
    }

    private class Renderer implements GLSurfaceView.Renderer
    {
        @Override
        public void onDrawFrame(GL10 gl) {
            gl.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

            // camera
            {
                gl.glMatrixMode(GL10.GL_PROJECTION);
                gl.glLoadIdentity();

                GLU.gluPerspective(gl, 45.0f, 1.0f, 0.01f, 100.0f);
                GLU.gluLookAt(gl, 0, 5.0f, 5.0f, 0, 0, 0.0f, 0.0f, 1.0f, 0.0f);
            }

            // vertices
            {
                final float one = 1.0f;

                final float[] vertices = new float[]{
                         one,   one,   one,
                         one,   one,  -one,
                        -one,   one,   one,
                        -one,   one,  -one,
                         one,  -one,   one,
                         one,  -one,  -one,
                        -one,  -one,   one,
                        -one,  -one,  -one,
                };

                FloatBuffer fb = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();

                fb.put(vertices);
                fb.position(0);

                gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
                gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fb);
            }

            {
                gl.glMatrixMode(GL10.GL_MODELVIEW);
                gl.glRotatef(1.0f, 0, 1, 0);// 回転
            }

            {
                final byte[] indices = new byte[]{
                        0, 1, 2,
                        2, 1, 3,
                        2, 3, 6,
                        6, 3, 7,
                        6, 7, 4,
                        4, 7, 5,
                        4, 5, 0,
                        0, 5, 1,
                        1, 5, 3,
                        3, 5, 7,
                        0, 2, 4,
                        4, 2, 6,
                };
                ByteBuffer bb = ByteBuffer.allocateDirect(indices.length).order(ByteOrder.nativeOrder());
                bb.put(indices);
                bb.position(0);
                gl.glColor4f(1, 1, 0, 1);
                gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, bb.capacity(), GL10.GL_UNSIGNED_BYTE, bb);
            }
         }

        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            gl.glViewport(0, 0, width, height);
        }

        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
       }
    }
}
package info.justoneplanet.android.glsample;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Bitmap.Config;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.opengl.GLUtils;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.SurfaceView;

public class MainActivity extends Activity {
    private GLSurfaceView gLSurfaceView;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        gLSurfaceView = new GLSurfaceView(this);
        gLSurfaceView.setRenderer(new Renderer());
        setContentView(gLSurfaceView);
    }

    @Override
    public void onPause()
    {
        super.onPause();
        gLSurfaceView.onPause();
    }

    @Override
    public void onResume()
    {
        super.onResume();
        gLSurfaceView.onResume();
    }

    private class Renderer implements GLSurfaceView.Renderer
    {
        private float aspect = 0.0f;
        private int vertices = 0;
        private int indices  = 0;
        private int indicesLength;

        @Override
        public void onDrawFrame(GL10 gl) {
            gl.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
            gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

            // camera
            {
                gl.glMatrixMode(GL10.GL_PROJECTION);
                gl.glLoadIdentity();

                GLU.gluPerspective(gl, 45.0f, 1.0f, 0.01f, 100.0f);
                GLU.gluLookAt(gl, 0, 5.0f, 5.0f, 0, 0, 0.0f, 0.0f, 1.0f, 0.0f);
            }

            {
                gl.glMatrixMode(GL10.GL_MODELVIEW);
                gl.glRotatef(1.0f, 0, 1, 0);
            }

            GL11 gl11 = (GL11) gl;
            gl11.glDrawElements(GL10.GL_TRIANGLES, indicesLength, GL10.GL_UNSIGNED_BYTE, 0);

         }

        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            aspect = (float) width / (float) height;
            gl.glViewport(0, 0, width, height);

            GL11 gl11 = (GL11) gl;
            {
                int[] buffer = new int[2];
                gl11.glGenBuffers(2, buffer, 0);

                vertices = buffer[0];
                indices = buffer[1];
            }

            // vertices
            {
                final float one = 1.0f;

                final float[] vertices = new float[]{
                         one,   one,   one,
                         one,   one,  -one,
                        -one,   one,   one,
                        -one,   one,  -one,
                         one,  -one,   one,
                         one,  -one,  -one,
                        -one,  -one,   one,
                        -one,  -one,  -one,
                };

                FloatBuffer fb = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();

                fb.put(vertices);
                fb.position(0);

                gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
                gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, this.vertices);
                gl11.glBufferData(GL11.GL_ARRAY_BUFFER, fb.capacity() * 4, fb, GL11.GL_STATIC_DRAW);

                gl11.glVertexPointer(3, GL10.GL_FLOAT, 0, 0);
            }

            {
                final byte[] indices = new byte[]{
                        0, 1, 2,
                        2, 1, 3,
                        2, 3, 6,
                        6, 3, 7,
                        6, 7, 4,
                        4, 7, 5,
                        4, 5, 0,
                        0, 5, 1,
                        1, 5, 3,
                        3, 5, 7,
                        0, 2, 4,
                        4, 2, 6,
                };
                ByteBuffer bb = ByteBuffer.allocateDirect(indices.length).order(ByteOrder.nativeOrder());
                bb.put(indices);
                indicesLength = bb.capacity();
                bb.position(0);

                gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, this.indices);
                gl11.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER, bb.capacity(), bb, GL11.GL_STATIC_DRAW);
            }
       }

        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        }
    }
}

androidのOpenGL ESでカメラを使う

こんな感じ。

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    gl.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

    {
        final float[] vertices = new float[]{
                0.0f,  1.0f,  1.0f,
                0.0f, -1.0f,  0.0f,
                1.0f, -1.0f, -1.0f,
        };

        FloatBuffer fb = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();

        fb.put(vertices);
        fb.position(0);

        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fb);
    }

    // カメラ
    {
        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();

        GLU.gluPerspective(gl, 45.0f, 1.0f, 0.01f, 100.0f);// 視野の設定
        GLU.gluLookAt(gl, 0, 0, 10.0f, 0, 0, 0.0f, 0.0f, 1.0f, 0.0f);// カメラの位置向き
    }
    gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 3);
}

インデックスバッファを使用すると以下のようになる。

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    gl.glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
    gl.glClear(GL10.GL_COLOR_BUFFER_BIT);

    {
        final float[] vertices = new float[]{
                0.0f,  1.0f,  1.0f,
                0.0f, -1.0f,  0.0f,
                1.0f, -1.0f, -1.0f,
        };

        FloatBuffer fb = ByteBuffer.allocateDirect(vertices.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();

        fb.put(vertices);
        fb.position(0);

        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glVertexPointer(3, GL10.GL_FLOAT, 0, fb);
    }

    // カメラ
    {
        gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();

        GLU.gluPerspective(gl, 45.0f, 1.0f, 0.01f, 100.0f);// 視野の設定
        GLU.gluLookAt(gl, 0, 0, 10.0f, 0, 0, 0.0f, 0.0f, 1.0f, 0.0f);// カメラの位置向き
    }

    // インデックスバッファ
    {
        final byte[] indices = new byte[]{0, 1, 2};
        ByteBuffer bb = ByteBuffer.allocateDirect(indices.length).order(ByteOrder.nativeOrder());
        bb.put(indices);
        bb.position(0);

        gl.glDrawElements(GL10.GL_TRIANGLE_STRIP, 3, GL10.GL_UNSIGNED_BYTE, bb);
    }
}

JavaScriptでプリム法

重み付き無向グラフの最小全域木を求めるアルゴリズム。任意の辺から始めて全頂点を覆うまで連続的に木の大きさを拡大し、全ての辺の重みの総和が最小となる経路を求める。

■実装

以下のように実装した。

/**
 * Vertex
 * @param int value
 */
var Vertex = function(value){
    var self = this;
    self.value    = value;
    self.neighbor = [];
    self.appendNeighbor = function(){
        for(var i = 0; i < arguments.length; i++){
            self.neighbor.push(arguments[i]);
        }
    }
}

// set up a graph
var v0 = new Vertex(0);
var v1 = new Vertex(1);
var v2 = new Vertex(2);
var v3 = new Vertex(3);
var v4 = new Vertex(4);
v0.appendNeighbor(
    {"vertex" : v1, "weight" : 2},
    {"vertex" : v3, "weight" : 8},
    {"vertex" : v4, "weight" : 4}
);
v1.appendNeighbor(
    {"vertex" : v0, "weight" : 2},
    {"vertex" : v2, "weight" : 3}
);
v2.appendNeighbor(
    {"vertex" : v1, "weight" : 3},
    {"vertex" : v4, "weight" : 1},
    {"vertex" : v3, "weight" : 5}
);
v3.appendNeighbor(
    {"vertex" : v2, "weight" : 5},
    {"vertex" : v4, "weight" : 7},
    {"vertex" : v0, "weight" : 8}
);
v4.appendNeighbor(
    {"vertex" : v2, "weight" : 1},
    {"vertex" : v3, "weight" : 7},
    {"vertex" : v0, "weight" : 4}
);
var V = [v0, v1, v2, v3, v4];

// initialize
var key  = [];
var pred = [];
for(var i = 0; i < V.length; i++){
    key[V[i]['value']]  = Number.POSITIVE_INFINITY;
    pred[V[i]['value']] = -1;
}
key[0] = 0;// 任意の1頂点をスタート地点とするため優先度を0にする
var bh = new BinaryHeap();
for(var i = 0; i < V.length; i++){
    // 頂点を優先度付きキューに格納
    bh.insert(V[i], key[V[i]['value']]);
}

// calc
while(bh.getList().length > 0){
    var u = bh.getPrior();// 優先度で先頭にくる頂点を取り出す
    for(var i = 0; i < u['neighbor'].length; i++){// 経路が存在している頂点でループ
        var neighbor = u['neighbor'][i]['vertex'];
        // 頂点(a)がキューに存在している場合
        if(bh.inQueue(neighbor)){
            var weight = u['neighbor'][i]['weight'];
            // かつ頂点(a)まで距離が前回のループまでに到達した距離よりも短い場合
            if(weight < key[neighbor['value']]){
                pred[neighbor['value']] = u['value'];// 頂点を配列に格納
                key[neighbor['value']]  = weight;// 距離を配列に格納
                bh.changePriority(neighbor, weight);// 優先度を更新(キューの先頭に近づく)
            }
        }
    }
}

// result
console.log("key:");
console.log(key);
console.log("pred:");
console.log(pred);

結果

最小全域木の距離の総和は以下を足した値となる。

0 2 3 5 1

計算時に辿った経路は以下のようになる。

-1 0 1 2 2

優先度付きキュー

以前の記事で使用したコードにメソッドを追記して使用した。

/**
 * BinaryHeap
 */
var BinaryHeap = function(){
    var self = this;
    self._ary  = [];
}
BinaryHeap.prototype._build = function(){
    var self = this;
    /**
     * heapify
     * 3要素を比較し最も小さい要素を親とする
     * @param {array} ary
     * @param {int} i
     * @param {max} max
     */
    var heapify = function(ary, i, max){
        /**
         * swap
         * @param {array} ary
         * @param {int} x
         * @param {int} y
         */
        var swap = function(ary, x, y){
            var a = ary[x];
            var b = ary[y];
            ary[x] = b;
            ary[y] = a;
            return true;
        }

        var l = 2 * i + 1;
        var r = 2 * i + 2;
        var li = 0;
        if(l < max && ary[l].priority < ary[i].priority){
            li = l;
        }
        else{
            li = i;
        }
        if(r < max && ary[r].priority < ary[li].priority){
            li = r;
        }
        if(li !== i){
            swap(ary, i, li);
            heapify(ary, li, max);
        }
    }
    var ary = self._ary;
    for(var i = ary.length - 1; i >= 0; i--){
        heapify(ary, i, self._ary.length);
    }
}
/**
 * BinaryHeap::insert
 * 要素をヒープに追加する
 * @param {Object} elm
 * @param {int} priority
 */
BinaryHeap.prototype.insert = function(elm, priority){
    var self = this;
    self._ary.push({
        "priority" : priority,
        "elm"      : elm
    });
    self._build();
}
/**
 * BinaryHeap::changePriority
 * 要素の優先度を変更する
 * @param {Object} elm
 * @param {int} priority
 */
BinaryHeap.prototype.changePriority = function(elm, priority){
    var self = this;
    var ary  = self._ary;
    for(var i = 0; i < ary.length; i++){
        if(elm === ary[i]["elm"]){
            ary[i]["priority"] = priority;
            self._build();
            return true;
        }
    }
    return false;
}
/**
 * BinaryHeap::getPrior
 * 優先度の高い要素を取得する
 */
BinaryHeap.prototype.getPrior = function(){
    var self = this;
    var elm  = self._ary.shift();
    self._build();
    return elm["elm"];
}
/**
 * BinaryHeap::getList
 * ヒープを返す
 */
BinaryHeap.prototype.getList = function(){
    var self = this;
    return self._ary;
}

/**
 * BinaryHeap::inQueue
 * ヒープ内で探索
 */
BinaryHeap.prototype.inQueue = function(v){
    var self = this;
    for(var i = 0; i < self._ary.length; i++){
        if(self._ary[i]['elm'] === v){
            return true;
        }
    }
    return false;
}

inQueueメッソドを効率よくできないかな・・・(●´⌓`●)

three.jsを通してWebGLを使う


※Google Chrome以外のブラウザでは正確に表示されない部分があります。

■サンプルコード

サンプルコードを大体そのまま動かしながらコードを理解してみる。

(function(){
    var camera, scene, renderer,
    geometry, material, mesh;
    init();
    animate();
    function init() {
        camera = new THREE.Camera(75, window.innerWidth / window.innerHeight, 1, 10000);
        camera.position.z = 1000;
        scene = new THREE.Scene();
        geometry = new THREE.Cube(200, 200, 200 );
        material = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true});
        mesh = new THREE.Mesh(geometry, material);
        scene.addObject(mesh);
        var canvas = document.getElementById('canvas2011030601');
        renderer = new THREE.CanvasRenderer();
        renderer.setSize(canvas.offsetWidth, 300);
        canvas.appendChild(renderer.domElement);
    }
    function animate() {
        // Include examples/js/RequestAnimationFrame.js for cross-browser compatibility.
        requestAnimationFrame(animate);
        render();
    }
    function render() {
        mesh.rotation.x += 0.01;
        mesh.rotation.y += 0.02;
        renderer.render(scene, camera);
    }
})();

CanvasRendererとあるようにどうやら普通にcanvasで描画しているようだ。

■サンプルコード

以下のようにアレンジしてWebGLRendererを使うようにしてみる。

(function(){
    var camera;
    var scene;
    var renderer;
    var mesh;
    // initialize
    (function(){
        camera = new THREE.Camera(75, window.innerWidth / window.innerHeight, 1, 10000);
        camera.position.z = 1000;
        scene = new THREE.Scene();
        mesh = new THREE.Mesh(
            new THREE.Cube(200, 200, 200),
            new THREE.MeshBasicMaterial({
                "color"     : 0xff0000,
                "wireframe" : true
            })
        );
        scene.addObject(mesh);
        var canvas = document.getElementById('canvas2011030602');
        renderer = new THREE.WebGLRenderer();
        renderer.setSize(canvas.offsetWidth, 300);
        canvas.appendChild(renderer.domElement);
    })();
    // animation
    setInterval(
        function(){
            mesh.rotation.x += 0.02;
            renderer.render(scene, camera);
        },
        1000 / 60
    );
});

以下のように表示される。

アンチエイリアスがないのが気になる。 しかしドキュメントが見当たらなかったのでWebGLRenderer.jsを開いてみた。

_antialias = parameters.antialias !== undefined ? parameters.antialias : false,

75行目あたりに上述の記述があるので、以下のようにオプションを指定した。

(function(){
    var camera;
    var scene;
    var renderer;
    var mesh;
    // initialize
    (function(){
        camera = new THREE.Camera(75, window.innerWidth / window.innerHeight, 1, 10000);
        camera.position.z = 1000;
        scene = new THREE.Scene();
        mesh = new THREE.Mesh(
            new THREE.Cube(200, 200, 200),
            new THREE.MeshBasicMaterial({
                "color"     : 0xff0000,
                "wireframe" : true
            })
        );
        scene.addObject(mesh);
        var canvas = document.getElementById('canvas2011030603');
        renderer = new THREE.WebGLRenderer({"antialias" : true});
        renderer.setSize(canvas.offsetWidth, 300);
        canvas.appendChild(renderer.domElement);
    })();
    // animation
    setInterval(
        function(){
            mesh.rotation.x += 0.02;
            renderer.render(scene, camera);
        },
        1000 / 60
    );
});

以下のようにアンチエイリアスがかかった。但し、Firefoxではアンチエイリアスがかからなかった。

meshを以下のように記述することでテクスチャを貼ることができる。

mesh = new THREE.Mesh(
    new THREE.Cube(
        200,
        200,
        200,
        3,
        3,
        3,
        [
            new THREE.MeshBasicMaterial({map: THREE.ImageUtils.loadTexture('/img/lock.png')}), // right
            new THREE.MeshBasicMaterial({map: THREE.ImageUtils.loadTexture('/img/face.png')}), // left
            new THREE.MeshBasicMaterial({map: THREE.ImageUtils.loadTexture('/img/face.png')}), //top
            new THREE.MeshBasicMaterial({map: THREE.ImageUtils.loadTexture('/img/face.png')}), // bottom
            new THREE.MeshBasicMaterial({map: THREE.ImageUtils.loadTexture('/img/face.png')}), // back
            new THREE.MeshBasicMaterial({map: THREE.ImageUtils.loadTexture('/img/face.png')}) // front
        ]
    ),
    new THREE.MeshFaceMaterial()
);

以下のように表示される。

現時点でWebGLに対応しているPCブラウザはGoogle Chrome、Firefoxとなる。残念ながらスマートフォンではandroidのデフォルトのブラウザやMobile SafariでWebGLを見ることはできず、android版のFirefoxでは見ることができる。ちなみにWebGLを使うとMacBookが熱々になる(●´⌓`●)

JavaScriptでフロイドワーシャル法

■実装

以下のように実装した。

//Graph
var vertexes = [
     [null, 2,    null, null, 4],//    vertex 1
     [null, null, 3,    null, null],// vertex 2
     [null, null, null, 5,    1],//    vertex 3
     [8,    null, null, null, null],// vertex 4
     [null, null, null, 4,    null]//  vertex 5
];

// initialize
var dist = [];
var pred = [];
var n    = vertexes.length;
for(var u = 0; u < n; u++){
    dist[u] = [];
    pred[u] = [];
    for(var i = 0; i < n; i++){
        dist[u][i] = Number.POSITIVE_INFINITY;// 経路が存在しない場合は無限
        pred[u][i] = -1;
        if(vertexes[u][i] !== null){
            dist[u][i] = vertexes[u][i];// 元グラフの経路を代入
            pred[u][i] = u;
        }
    }
    dist[u][u] = 0;// 自身に対しては0の距離が存在する
}
console.log('dist:');
console.log(dist);//...(a)

// 計算
for(var k = 0; k < n; k++){
    for(var i = 0; i < n; i++){
        if(dist[i][k] === Number.POSITIVE_INFINITY){
            continue;
        }
        // 任意の頂点まで有限の距離が開いているとき
        // 有限距離 を経由した任意の頂点を選択し
        // そこまでの距離が既に計算したものよりも小さい場合に
        // その値で上書きする
        for(var j = 0; j < n; j++){
            var newLength = dist[i][k];// ik
            newLength += dist[k][j];
            if(newLength < dist[i][j]){
                dist[i][j] = newLength;
                pred[i][j] = pred[k][j];
            }
        }
    }
}

// 結果
console.log("dist:");
console.log(dist);//...(b)

(a)の時、distは以下のようになる。

0 2 Infinity Infinity 4
Infinity 0 3 Infinity Infinity
Infinity Infinity 0 5 1
8 Infinity Infinity 0 Infinity
Infinity Infinity Infinity 4 0

殆ど元グラフと変わらない。結果(b)は、以下のようになる。

0 2 5 8 4
16 0 3 8 4
13 15 0 5 1
8 10 13 0 12
12 14 17 4 0

例えば0→1は距離が2、0→2は距離が5、0→3は距離が8、0→4は距離が4であり、1→0は距離が16である。

経路

終了時のpredは以下のようになる。

-1 0 1 4 0
3 -1 1 2 2
3 0 -1 2 2
3 0 1 -1 0
3 0 1 4 -1

例えば0→1の一つ前の頂点は始点0、0→2の一つ前の頂点は頂点1、0→3の一つ前の頂点は頂点4、0→4の一つ前の頂点は0であり、1→0の場合は頂点3が終点の一つ前である。

■おまけ

ちなみに表は以下のようにして描画した。

document.write('<table border="1" cellpadding="0" cellspacing="0">');
dist.forEach(function(e1, i1, ary1){
	document.write('<tr>');
	e1.forEach(function(e2, i2, ary2){
		document.write('<td>' + e2 + '</td>');
	});
	document.write('</tr>');
});
document.write('</table>');

そろそろJavaScriptでもforEachを使って良い頃だと思う。