2014年11月25日火曜日

逆行列を求める手順

たまにオレオレ行列ライブラリを作りたくなり,逆行列を求める手順を書くところで公式が長くて忘れていて調べ回る,ということをしているので作り方をメモしておく.

ある行Rとある列Cを取り除いた行列の行列式に(-1)の(R+C)乗を掛けたものを余因子と言う.

ある行またはある列の要素全てについて,余因子を求めて足し合わせると行列式が求まる.よって,これを1次正方行列になるまで繰り返せば,行列式を求める手順が分かる.

行列式が0でない場合,逆行列が作れて,行R列Cの要素は余因子で,最後に全ての要素に行列式の逆数を掛ければ良い.

2014年11月19日水曜日

UE4で作ったものをOculus Rift DK2で見るまで

Oculus Rift DK2が届いたので,さっそくUE4で作ったものを見れるようにしてみよう,と思ったものの,いろいろ引っかかったので手順をまとめておく.


  • OS - Windows 8.1 Pro
  • CPU - Intel Core i7 4710MQ
  • GPU - GeForce GTX 860M version 9.18.13.4475
  • UE4 - UE4.5.1

まず,Oculusの公式サイトの右上のデベロッパから開発者向けサイトに移動する.


Downloadsタブを選び,0.4.2 betaからWindows Runtimeをダウンロードし,インストールする.注意したいのが,2014/11時点で0.4.3のRuntimeをインストールすると,UE4が立ち上がらなくなる場合があるなど問題が起こることがあるので,0.4.2を選ぶこと.


インストールが終わり,接続も済んだら,今度はディスプレイの設定を変更する.コントロールパネルを開き,デスクトップのカスタマイズを選ぶ.


ディスプレイを選ぶ.


左のメニューから,セカンドディスプレイに表示,を選ぶ.


拡張を選ぶ.どうも拡張を選んでおかないと,PCのディスプレイの解像度によっては上手く動かなくなるらしい.


左メニューの解像度の調整を選び,セカンダリディスプレイ(2と表示されている)になっているDK2を選び,向きを横(反対向き)にする.


適当なUE4のプロジェクトを開き,プレイボタンの右側の小さい三角をクリックしてメニューを開き,スタンドアローンゲームを選択する.


起動後,Alt+Enterを押してOculus Riftに表示されれば成功.ただし,時折失敗する場合があり,その場合はShift + Windowsキー + 右でウィンドウをOculus側に移動させ,改めてAlt + Enterを押すと表示される.

終わる場合は,再度Alt + Enterを押して通常画面に戻し,Shift + F1でUE4ゲームのマウス操作モードを抜け,右上の×ボタンを押せば良い.

Shift + Windowsキー + 右でウィンドウを移動させた場合,Shift + Windowsキー + 左でウィンドウを元のディスプレイに戻すなど必要かもしれない.

2014年10月17日金曜日

UMGのプロパティバインディングとスライダーを使ってみた

UMGのブループリントに変数を追加し,UMGのコンポーネントと連動させることができるようなので,それを利用してテキストボックスとスライダーを連動させてみた.

Widgetブループリントの生成


ここでは,SampleWidgetBPというWidgetブループリントを作成し,Editable Text BoxとSliderを配置し,それぞれValueTextとValueSliderという名前にしてみた.

変数の追加


次に,グラフからプロパティとして利用するFloatの変数Valueを追加しておく.

ValueTextのテキストの取得と設定に関する設定

まず,テキストボックスに変数Valueの値を取得して変換して設定するようにする.


更に,テキストボックスが編集された場合にValueに値を設定し,Sliderの値も変更するようにする.(Sliderには設定しなくてもできる気もする)



ValueSliderの値の取得と設定


ValueTextと同様に,詳細のValueを変数Valueを参照するようにしたり,値が変化した際にValueに設定するようにしている.




Widgetの表示


最後に,レベルブループリントなどからWidgetを生成して,Add to Viewportで画面に出せば,Sliderの変化に合わせてテキストボックスの値が変わり,テキストボックスの変更に合わせてスライダーが移動するUIが完成する.


最後に

SliderにプロパティとしてValueを設定しているところをバインディングに変更すれば,Sliderに値を設定する部分は不要かもしれないが・・・眠いのでまた明日にしよう.

2014年10月15日水曜日

Unreal Motion Graphics (UMG)でプログレスバーを表示してみた

UMGでプログレスバーを作ってみました.

UMGを有効にするには,メニューの編集からエディタの設定を選びます.

実験的,の項目からUMGにチェックを入れ,エディタを再起動します

コンテンツブラウザから新規のアセットを追加します.右クリックメニューからユーザーインターフェースの中のWidgetブループリントを選びます.

できたブループリントのファイルをダブルクリックして開くと,UMGのエディタになるので,適当にプログレスバーを配置し,名前をProgressに変更しておきます.終わったらコンパイルしておきます.

レベルブループリントを開き,追加したブループリントの名前のオブジェクトの変数を作ります.(この図では手抜きでデフォルトの名前のまま).そして,Begin Playイベント時にCreateWidgetを利用して作成したWidgetを生成します.CreateWidgetに作成したブループリントを指定すると,Widgetが生成できます.CreateWidgetが返すのはUserWidget型のオブジェクトなので,キャストを挟んで変数に設定します.

このWidgetから線をひっぱり,Add to Viewportを呼び出すと,画面に表示されます.

Progressと名付けたfloat型の変数を追加しておき,Begin Playイベント時に0で初期化しておきます.

Tickイベントで毎フレーム0.001ずつProgressの値を増やします.ただし,100を超えないようにします.

最後に,Widget変数から線をひっぱりGet Progressと打つと,プログレスバーのオブジェクトが取得できます.そこから更に線をひっぱると,Set Percentというものがあるので,そこに変数Progressの値を設定します.

これをコンパイルして再生すると,プログレスバーが徐々に進んでいきます.

他のUIもいろいろ触ってみたくなってきました.

2014年10月13日月曜日

glLoadGenを使う場合の注意点

OpenGL 4 Shading Language Cookbook, 2nd Editionを読んでいて,いきなり躓いた.

第一章で導入するglLoadGenが,ダウンロードできる最新版だと上手く動かない.
こちらに書いてあるように問題があるので,こちらを参照して手元のものを書き直すか,Mercurialを使って最新版をダウンロードする必要がある.

次に,Windows上で実行した場合,何故かバージョン指定を"(ダブルクオーテーション)で囲む必要があった.
(PowerShellを使っているせいか?)

この点を修正すると,ようやく動かすことができた.

2014年10月7日火曜日

WebGLによるPVRテクスチャの利用

DDSの読み込みを作った勢いで,iOSのWebGL向けにPVRテクスチャを読み込む処理を書いてみた.

動作サンプルはこちら
iOS 8以降で確認できます.

// 拡張機能の取得
var ct = gl.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc");

// FCCを32bit符号付き整数に変換する
function FourCCToInt32(value){
    return (value.charCodeAt(0) << 0) +
        (value.charCodeAt(1) << 8) +
        (value.charCodeAt(2) << 16) +
        (value.charCodeAt(3) << 24);
}

// 32bit符号付き整数をFCCに変換する
function Int32ToFourCC(value){
    return String.fromCharCode(
        (value >> 0) & 0xff,
        (value >> 8) & 0xff,
        (value >> 16) & 0xff,
        (value >> 24) & 0xff
    );
}

// XMLHttpRequestの生成
var XHR = new XMLHttpRequest();

// 読み込むファイルの指定
XHR.open('GET', './sample4.pvr');

// 読み込み完了時の処理
XHR.addEventListener('load', function(){
    // iOS Developer Libraryより
    // PVRTextureLoaderを参照
    // https://developer.apple.com/library/ios/samplecode/PVRTextureLoader/Introduction/Intro.html
    var header = new Uint32Array(XHR.response, 0, 13);
    var tag = Int32ToFourCC(header[11]);

    if(tag != "PVR!"){
        alert("PVRフォーマットではありません.");
        return ;
    }

    var hasAlpha = header[10] != 0 ? true : false;
    var PVR_TEXTURE_FLAG_TYPE_MASK = 0xff;
    var PVR_TEXTURE_FLAG_TYPE_PVRTC_2 = 24;
    var PVR_TEXTURE_FLAG_TYPE_PVRTC_4 = 25;

    var height = header[1];
    var width  = header[2];

    var format = 0;
    var blockSize = 0;
    var blockWidth = 0;
    var blockHeight = 0;
    // 1ピクセルあたりのビット数
    var bpp = 0;
    switch(header[4] & PVR_TEXTURE_FLAG_TYPE_MASK){
    case PVR_TEXTURE_FLAG_TYPE_PVRTC_2:
        if(hasAlpha){
            format = ct.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
        }else{
            format = ct.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
        }
        blockSize = 8 * 4;
        blockWidth = width / 8;
        blockHeight = height / 4;
        bpp = 2;
        break;
    case PVR_TEXTURE_FLAG_TYPE_PVRTC_4:
        if(hasAlpha){
            format = ct.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
        }else{
            format = ct.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
        }
        blockSize = 4 * 4;
        blockWidth = width / 4;
        blockHeight = height / 4;
        bpp = 4;
        break;
    default:
        alert("未知のフォーマットです.\n");
        return ;
    }

    // 最低限のサイズはあるものとする
    blockWidth = Math.max(2, blockWidth);
    blockHeight = Math.max(2, blockHeight);

    var size = blockWidth * blockHeight * ((blockSize * bpp) / 8);
    var buffer = new Uint8Array(XHR.response, 13 * 4, size);

    // 圧縮テクスチャを渡す
    gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, buffer);

    // テクスチャのパラメータを設定
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);

    // テクスチャを設定して有効化
    gl.uniform1i(gl.getUniformLocation(program, 'texture'), texture);
    gl.activeTexture(gl.TEXTURE0);

    // 描画開始
    draw();
});
// バイト配列として結果が帰ってくるようにする
XHR.responseType = 'arraybuffer';

// 読み込み開始
XHR.send();

処理としてはDDSを読み込む場合とほとんど変わらず,違いというと,取得する拡張機能の名前が違うことと,受け取ったバイト列をフォーマットに合わせる部分.

このコード書くの,何が大変だったかってpvrのテクスチャを生成するのが手間だったのと,iOSでチェックするためのデバッグが面倒だった.Safariを使ってiOS上で見ているウェブページをデバッグする機能が無かったら大変だった.

2014年10月6日月曜日

PVR形式のテクスチャの作り方

忘れそうなのでメモ.

xcrun -sdk iphoneos texturetool [-m] -e PVRTC --bits-per-pixel-4 -o outputfile -f PVR inputfile
# -m でミップマップ生成
# --bits-per-pixel-2も