2013年12月21日土曜日

Nexus 5がWEB版Google Playに表示されない問題及びAndroidデバイスマネージャーに表示されない問題をGoogleに問い合わせてみた話 ( 解決しませんでした )

最初に言っておきますが、解決しませんでした。

ただ、原因が分かった事と、場合によっては改善するかもしれない方法を中の人にご教授頂いたので、それをここに載せておきたいと思います。

Nexus 5がWEB版Google Playに表示されない理由とAndroidデバイスマネージャーに表示されない理由


Nexus 5が上記の問題を引き起こす原因は、Android 4.4にその原因がある。Android 4.4 KitKatにおいて、Google Play開発者サービスに包含されるアプリケーションであるGoogle設定の位置情報の管理方法が変更されたことが直接の原因だ。

Android 4.3のGoogle設定->位置情報

Android 4.4のGoogle設定->位置情報

WEB版Google Playを介して端末にアプリケーションや、その他のコンテンツをダウンロードするには、「位置情報へのアクセス」する必要があるが、「Android 4.4 を搭載する Nexus 端末では利用できない」。

参考 : [Google設定] での位置情報の管理 - Google アカウント ヘルプ

Google Play ヘルプのお問い合わせから問い合わせて、Google Playストアに表示されない問題に対する4つの解決方法(後述)を試した後、Androidのバージョン、Google Playストアのビルドバージョン等の追加情報と共に再度問い合わせた所、Google設定で位置情報アクセスが利用出来ないことが原因である、と伝えられた。

非常に迅速な対応をして頂き、理由が明確に分かったのも素晴らしいが、Android 4.4にバージョンアップしたことで利用できなくなる、というのは甚だ残念だ。出来れば早めに改善して頂けると喜ばしい。

Androidデバイスマネージャーを利用出来ないのも同じ理由だろう。どう考えても同アプリは位置情報へのアクセスが必須であるので、その為利用できないのだろう。


Androidデバイスマネージャーは上記の画面で延々とロードし続ける。

もしNexus 5で上記の問題が発生していない方、解決した方は連絡下さると嬉しいです。

問題を解決しうる4つの方法

残念ながらAndroid 4.4では解決しなかったが、4.3以下では以下の方法で解決しうることをGoogleサポートの中の人からご享受いただいたのでここに載せる(原文ママ)

-------

【 A 】 アカウントの入れ直し
※アカウントの情報が消えることはございませんので、ご安心ください。

1. メニュー > [設定] > [アカウントと同期] に移動します。

2. 削除するアカウントの名前をタップして、メニュー > [アカウントを削除] をタップします。

アカウントの削除後に、次の手順を行うことで再度アカウントを端末に追加することができます。

3. メニュー > [設定] > [アカウントと同期] に移動し、[アカウントを追加] をタップします。

4. 表示される手順どおりにアカウント情報を入力し再度追加します。

-------

【 B 】 端末の再起動

-------

【 C 】 Play ストア アプリのキャッシュとデータの消去

1. [設定] > [アプリ] > [すべて] を開きます。

2. 下にスクロールして [Google Play ストア] をタップします。

3. [キャッシュを消去] [データを消去] をタップします。

-------

【 D 】 Play ストアのアップデートをアン インストール

1. [設定] > [アプリ] > [すべて] を開きます。

2. 下にスクロールして [Google Play ストア] をタップします。

3. [アップデートのアン インストール] をタップし、出荷状態に戻します。

4. 再度 Play ストア アプリ を開き、しばらくすると、最新版に 更新されます。

-------

2013年12月14日土曜日

初めてテンプレートメタプログラミングに触れてみた

初めてテンプレートメタプログラミングというものに触れた。 正直今でも何が起こっているのかは理解できてない。 以下はテンプレートメタプログラミングで整数の整数乗を求めるプログラム。 尚、型は全てint。

#include <iostream>

// default
template< int base, int iexp, bool = iexp >= 0 >
struct Pow{
	// fallback for iexp < 0
	static const int value = 0;
};

// specialization for iexp >= 0
template< int base, int iexp >
struct Pow< base, iexp, true >{
	// base ^ iexp = base * base ^ ( iexp - 1 )
	static const int value = base * Pow< base, iexp - 1 >::value;
};

// specialization for iexp == 0
template< int base >
struct Pow< base, 0, true >{
	// base ^ 0 = 1
	static const int value = 1;
};

int main( void ){
	std::cout << "2 ^ -2 = " << Pow< 2, -2 >::value << std::endl;
	std::cout << "2 ^ -1 = " << Pow< 2, -1 >::value << std::endl;
	std::cout << "2 ^  0 = " << Pow< 2,  0 >::value << std::endl;
	std::cout << "2 ^  1 = " << Pow< 2,  1 >::value << std::endl;
	std::cout << "2 ^  2 = " << Pow< 2,  2 >::value << std::endl;

	return 0;
}
コンパイル時定数では浮動小数点実数は扱えない(constexpr等の例外を除く)らしい(嘘をついているかも)ので、 扱う変数valueの型はstatic const int型としている。

そのため、負数乗は全て0とした。 iexpが0未満の時は全てデフォルトの定義になる。

0乗は1、自然数乗は再帰を行うように定義している。

よく分かっていないのは bool = iexp >= 0 という式。 型だけ書いて変数名(識別子)を書かないのはテンプレートだから許されるのだろうか。 おそらく、関数のプロトタイプ宣言をする時に、形名だけを書くのと似たようなものだろうと思っている。 どちらも同じ「引数」だし。

あと、2つ目の定義と3つ目の定義のどちらを使用するのかをコンパイラがどうやって決めているのかもよく分かんない。 C++怖い。

あ、間違いあったら教えて下さい。

2013.12.16追記 ※constexprが使える環境ならconstexprを使うべきと思われる。
このコードはMSVC++2008で書いたのでconstexprは使えなかった。

2013年11月24日日曜日

[ネタバレ] ECCO THE DOLPHIN 2の翻訳が英語と日本語訳で全く違う件について

ECCO THE DOLPHIN 2は私が特別に好きなゲームの一つである。
このゲームのラストでプレイヤーに提示される「SECRET PASSWORD」の意味が今の今まで分からず、
ふとしたきっかけで検索したら、以下のページを見つけた。

名作アルバム -『エコー・ザ・ドルフィン』-

セガの名作アルバムである。現在トップページからどのような経路で到達できるかは不明。
このコンテンツの中で興味深い記述を見つけた。
ローカライズを担当された長谷川亮一氏のインタビューだ。

P2
……私は機械的な翻訳は嫌だったので、無機質にならないように、血の通ってる翻訳がしたいと常々思っていました。だから、ただの翻訳だけでなく、プラスアルファとしてストーリーを語ったり、ルールの説明をしたり、かなりの情報を詰め込んだつもりです。
(引用ここまで)

P3
普通の本とか見て方眼紙に点を打つんですよ。(中略)向こうは何を打ってるのか全然わかってないわけですよ(笑)
(引用ここまで)

という事で、かなりの意訳が成されているらしい。

おもいでがいっぱい
今回驚かされたのはメッセージを長谷川さんが書かれていたことです。あのメッセージは谷川俊太郎顔負けの名訳だと思っています。
(引用ここまで)

感想の所には上記のようなメール内容も載せられていた。
私も本当に頑張ってクリアして、エンディングのメッセージには涙を流した。
小さな平仮名とカタカナだけの文章でありながら、今見ても胸が苦しくなる、本物の名訳である。

という訳で、エンディングの翻訳文と原文を比較してみた。

以下原文
Epilogue

The Queen retreats
within her machine.
When ecco leaves she
escapes in the form of
a Vortex larva.

The Queen makes her way
to the sunken city of
Atlantis. She finds the
time machine and escape
into Earth's past.

When the Queen arrives
in the prehistoric era,
She encounters creatures
that she cannot rule.
She has no choice but to
live within the life
cycles of the earth.

And, through the eons,
the Vortexkind integrate
with the life on earth.

Ecco finds the time
machine in the City of
forever. Instead of
destroying it, he uses
it and disappears into
the tides of time.

以下翻訳文
エピローグ

エコーは ながい たびのはてに
とうとう タイムマシンをみつけました。

マシンをはかいすれば すべてが
おわるのです。

、、、ほんとうにおわるのでしょうか、、、

かれは アステライトのことばを
おもいだします、、、
かれのそんざいじしんが
じかんの ぶんきてんなのです。

かれは なかまの イルカのことばを
おもいだします、、、

かれの あたまのもようは
うんめいの しるしなのです。

、、、ほんとうにおわるのでしょうか、、、

かれは すべてをおえる ただひとつの
ほうほうを みつけました、、、

タイムマシンを はかいするかわりに
エコーは ときのとびらをひらくと、
えいえんの じかんのながれのなかに
きえていったのです、、、

最後の部分以外がまるで違う文章に置き換えられている。
英語版は最後に何が起きたのかを、説明的な文章で解説している一方で、
日本語版は、エコーの決断を詩的かつ叙情的に表現している他、
何故エコー自身が何故時間の流れの中に消えていく必要があったのか(エコーの存在自身が時間の分岐点だから、という理由に納得が行くかどうかは別として)を説明している。

英語版のボルテックス・クイーンを倒した際に現れる謎の生物が何だったのかを解説の私による翻訳を載せる。
エピローグ

クイーンは彼女のマシンの中へと退却した。
エコーが去る時、彼女はボルテックスの幼生へと姿を変えて逃げた。

クイーンはアトランティスの水没都市への道を開いた。
彼女はそこでタイムマシンを見つけ、
過去の地球へと逃亡した。

クイーンが有史以前の時代に到着した時、
彼女は彼女には支配出来ない生物たちに遭遇した。
彼女はやむなく地球上のライフサイクルの中で生きていく他無かった。

そして、長い時の流れを経て、
ボルテックスの種は地球上の生命の中に統合されてしまった。

エコーは永遠の街でタイムマシンを見つけた。
彼はそれを破壊する代わりに、
それを使い、時の潮の中へと消えていったのだ。

以上である。ボルテックス・クイーン撃破時に現れ、
CITY OF FOREVERで登場する「かれら」はボルテックスの幼生が地球上の生物の系統の中に統合されたものだったのである。
これらの情報が欠けてしまっているのは残念ではあるが、心に訴えかける素晴らしい名訳であると思う。

ちなみに、最後のSECRET PASSWORDは以下の様な経緯で出来た代物らしい。

おもいでがいっぱい
エンディングのパスワードの件、真相をお教えしましょう。
実はあのパスワードを解析プログラムに入れると、総プレイ時間やミスの数、パズルを解いた効率の良さなどがかなり詳細に分かるのです。
これで「ゲームを一番上手くクリアできた人コンテスト」が出来るようにと開発元が仕込んでくれたのですが、残念ながら日本ではコンテストの企画が通らず(集計が大変だ、というのが理由です。今みたいにネットで応募、とか出来ませんしね)、あのパスワード画面だけが残ってしまった、という訳なのです。

(解析プログラムはフロッピーに入れてマスターROMと一緒に保管したので、今でもセガのどこかにあるんじゃないかなぁ?)
(引用ここまで)

この記述を見る限りは、無印の話なのか2の話かは判然としないが、
私は2しかやっておらず、このパスワードも2で表示されたので恐らく2の話だろう。

2013年11月5日火曜日

C++の名前空間のネストと識別子の衝突と無名名前空間について

私は普段DXライブラリを使っているのだが、 先日、以下の様なコードを書いた所エラーが出た。 ちなみに簡略化された全く意味のないコートであることに留意されたし。

#include "lua.hpp"
#include "DxLib.h"

namespace Lua{
	int Func( lua_State* pLuaState ){
		return 0;
	}
}
namespace DxLib{
	namespace Lua{
	}
}
void Test( void ){
	lua_State* p = NULL;
	Lua::Func( p );
}

エラーの内容は以下のとおり。

error C2872: 'Lua' : あいまいなシンボルです。
'Lua' である可能性があります。
または 'DxLib::Lua'

DXライブラリは、 DxLib.h 内で、名前空間 DxLib を using 宣言している。 このため、名前空間 DxLib::Lua と 名前空間 Lua をコンパイラが区別する事ができず、 コンパイルエラーとなっている。

C++において、普通に宣言した識別子は、無名名前空間(グローバル名前空間とも呼ばれる)に所属している。 無名名前空間に属している事を明示するためには、識別子をスコープ演算子から書き始める。 この記法を用いて修正したコードは以下のとおり。(関数 Test のみ)

void Test( void ){
	lua_State* p = NULL;
	::Lua::Func( p );
}

本当なら、関数 Func は名前空間 Lua にのみ存在するので、参照自体は出来ると思うのだが・・・ もしかしたらVC++ 2010でコンパイル出来ないだけで、他のコンパイラだと通るかもしれない。C++怖い。

ちなみに、以下の様な、識別子を使わない名前空間も無名名前空間と呼ぶ。

namespace{
	...
}

この名前空間内に記述した識別子は、同じソースコード内でしか参照できなくなる。 C++では、 static 修飾子よりも無名名前空間を使用することが推奨されている[要出典]

2013年11月4日月曜日

Luaを使ってクラスっぽい物を生成してCから使う方法 修正版

2013.11.04 追記

以前の投稿が激しく誤った情報を載せていたので修正。

Luaでクラス風のオブジェクトのメンバ関数を呼ぶ際は、 lua_pushvalue 関数を用いて、オブジェクトそのものを引数としてスタックにプッシュしてやる必要がある。

今回はメンバ関数内でオブジェクトのメンバを書き換えていないため、これでも正しく動作するが、 もしメンバ関数内でメンバを書き換える場合は、オブジェクト自身を return し、 lua_replace 関数を用いて返り値を元のオブジェクトに上書きしてやる必要がある。詳細は別途記事を書く予定。
2013.11.04 昨日はそうしないとうまく動かなかった筈ですが今日やったら動きました。 lua_pushvalue でコピーしたテーブルの内容を書き換えた場合って、参照元も書き換わるのかな… よく分からんのでもし分かる人がいらっしゃったらコメントとかで教えて下さい。

main.cpp

#include <lua.hpp>
#include <stdio.h>

int main( void ) {
	lua_State* L = luaL_newstate();	// Luaステートを生成
	luaL_openlibs( L );				// 標準ライブラリを読み込み

	// スクリプトの読み込み
	if( luaL_dofile(L, "script.lua") ){
		// エラー処理
		printf( "%s\n", lua_tostring( L, lua_gettop(L) ) );
		lua_close( L );
		return 0;
	}

	// 犬を生成
	lua_getglobal( L, "Dog" );					// グローバルなテーブル"Dog"をスタックに積む
	lua_getfield( L, lua_gettop( L ), "new" );	// トップに積まれたテーブルのメンバ"new"をスタックに積む
	lua_pushstring( L, "Neko" );				// 名前はNeko。犬なのにNeko。
	lua_pcall( L, 1, 1, 0 );					// 実行。関数と引数はスタックから除去され、返り値が積まれる
	lua_remove( L, -2 );						// 返り値の下にあるDogを除去
	int idx_dog = lua_gettop( L );				// Nekoのスタック上の位置を取得

	// 猫を生成
	lua_getglobal( L, "Cat" );					// グローバルなテーブル"Cat"をスタックに積む
	lua_getfield( L, lua_gettop( L ), "new" );	// トップに積まれたテーブルのメンバ"new"をスタックに積む
	lua_pushstring( L, "Inu" );					// 名前はInu。猫なのにInu。
	lua_pcall( L, 1, 1, 0 );					// 実行。関数と引数はスタックから除去され、返り値が積まれる
	lua_remove( L, -2 );						// 返り値の下にあるCatを除去
	int idx_cat = lua_gettop( L );				// Inuのスタック上の位置を取得
	
	printf( "%d object\n", lua_gettop( L ) );	// スタックのサイズが正しい事を確認

	// メンバ関数showを呼び出し
	lua_getfield( L, idx_dog, "show" );	// 関数をスタック
	printf( "%d object and function\n", lua_gettop( L ) );
	lua_pushvalue( L, idx_dog );		// 引数selfをスタック
	printf( "%d object, function, and argument\n", lua_gettop( L ) );

	// 実行
	if( lua_pcall( L, 1, 0, 0 ) ){
		// エラー出力
		printf( "%s\n", lua_tostring( L, lua_gettop( L ) ) );
	}
	
	printf( "%d objects\n", lua_gettop( L ) );
	
	// メンバ関数showを呼び出し
	lua_getfield( L, idx_cat, "show" );	// 関数をスタック
	printf( "%d object and function\n", lua_gettop( L ) );
	lua_pushvalue( L, idx_cat );		// 引数selfをスタック
	printf( "%d object, function, and argument\n", lua_gettop( L ) );

	// 実行
	if( lua_pcall( L, 1, 0, 0 ) ){
		// エラー出力
		printf( "%s\n", lua_tostring( L, lua_gettop( L ) ) );
	}
	
	printf( "%d object\n", lua_gettop( L ) );

    lua_close( L );	// 終了
    return 0;
}

script.lua

-- Dog
Dog = {}
Dog.new = function( name )
	local obj = {}
	obj.name = name
	obj.show = function( self )
		s = string.format( "%s the DOG.", self.name )
		print( s )
	end
	return obj
end

-- Cat
Cat = {}
Cat.new = function( name )
	local obj = {}
	obj.name = name
	obj.show = function( self )
		s = string.format( "%s the CAT.", self.name )
		print( s )
	end
	return obj
end

2013年11月1日金曜日

BloggerでSyntaxHighlighterを利用する際のTIPS

前の記事で、SyntaxHighlighterを導入してソースコードをBlogger上で表示した。 Luaの表示には公式ウェブサイトからリンクされているサイトの追加ブラシのLua1を利用した。 SyntaxHighlighterを使う際に以下のような問題に遭遇したため、ここにその対処法を示す。
  • Bloggerでは任意のファイルをアップロード出来ない
  • 記事上で、<等の特殊文字がうまく表示できない
  • タブが半角スペースに置換され、インデントがずれる
  • 全ての行の背景が同じ色で表示されるため、少し見辛い
  • shThemeXxx.css と shCoreXxx.css の違いが分からない

Bloggerでは任意のファイルをアップロード出来ない

Bloggerでは、任意のファイルをアップロードする事はできない。よって、JavaScriptやCSSをBloggerのドメインでホスティングする事は出来ず、Alex氏がホスティングしているファイルを参照する事になる。
別にそれはそれで構わないのだが、出来れば自分でホスティングしたい。それに、Syntax Highlighterがサポートしていない形式のコードを扱う時は困る(これも、その作者がホスティングしてくれているファイルを参照すれば問題ないが、精神的によろしくない)。
Google サイトを使った方法や、Google ドライブを利用する方法等があるようだが、いずれも欠点を抱えているようなので、私のオススメはDropboxを利用することである。
ここで注意したいのが、DropboxでのファイルのURLを生成する方法は二種類あることだ。
Publicフォルダに置いたファイルは「公開リンクをコピー」することで、そのURLを取得出来る。この方法で取得するURLには一意なユーザIDと、Publicフォルダ内におけるディレクトリ情報が含まれる。複数のハンドルネームを使っている場合等、「このファイルとあのファイルが置かれているアカウントは同じアカウントだ」とバレたくなければ使わないほうがいいだろう。ただし、内部的に相対パスを利用するファイルではこちらの方法が必須となる。
尚、生成されるURLは https://dl.dropboxusercontent.com/u/userID/filename だ。
Publicフォルダ以外に置いたファイルは「Dropbox リンクを共有」の機能を使用することで、URLを生成することができる。こちらの方法で生成したURLは、どのアカウントのファイルなのかを含め、隠蔽される。相対パスは利用できないが、よりセキュアであると言える。
生成されるURLは https://www.dropbox.com/s/fileID/filename だ。
参考:

記事上で、<等の特殊文字がうまく表示できない

HTMLでは一部の特殊文字は文法上の記法に利用されるため、エスケープシーケンスが必要となる。 置換にはこのサイトを利用した。
HTML特殊文字変換|コードをホームページに載せる時に便利 | すぐに使える便利なWEBツール | Tech-Unlimited 他にもあるかも知れないし、ローカルで出来るようなプログラムがあった方が良いかもしれない。

タブが半角スペースに置換され、インデントがずれる

Bloggerでは、タブが半角スペースに勝手に置換されるため、ソースコードのインデントがずれる。 プレビューではちゃんと表示されるのに、保存、公開した途端に置換されるのが曲者だ。 投稿時の編集のモードをHTMLにし、タブを &#9; に置換して記述することで、この現象を避けることが出来る。 ただし、一度編集のモードを作成にすると、せっかく置き換えたタブが半角スペースに戻ってしまうため注意。 公開後、きちんと投稿後の記事を確認した方が良いだろう。

全ての行の背景が同じ色で表示されるため、少し見辛い

これは、SyntaxHighlighterのCSSを編集することで改善できる。 .syntaxhighlighter .line.alt1 と .syntaxhighlighter .line.alt2 のそれぞれに背景色を設定してやればよい。 詳細は Syntax Highlighterの背景色と行間を変更する | ジャイアントモリンキーのjavaテック を参照。

shThemeXxx.css と shCoreXxx.css の違いが分からない

shCoreXxx.css は shCore.css と shThemeXxx.css を合成したものである。 参考: そらとぶくじら。 SyntaxHighlighter

以上。

2013年10月22日火曜日

Luaを使ってクラスっぽい物を生成してCから使う方法

2013.11.04 修正版記事を作りました。
2013.11.04 大きな間違いに気がついたので後日書き直します。本記事は大嘘です。
2013.11.01 誤って記事を消してしまったので書き直し。

本記事は間違いだらけです。修正版はこちら。


以下のようなコードによって、Luaで簡単なクラス風のテーブルを作成できる。

クラス風のテーブルを作成する方法はWEB上に多数のサンプルが見受けられたが、 Cとの連携を付記したコードは見当たらなかったので備忘録として作成。

継承にはもう少し工夫が必要だが、複雑なテーブルを作成するならC++で普通にクラスを書いたほうが良い気がする。主観だが。

Luaでグローバル領域に宣言されたテーブルのフィールドを利用する際は、一度テーブルをスタックに積んでからフィールドを取得する点に注意。

main.cpp

#include <lua.hpp>
#include <stdio.h>

int main( void ) {
	lua_State *L = luaL_newstate();	// Luaステートを生成
	luaL_openlibs( L );				// 標準ライブラリを読み込み
	
	// スクリプトの読み込み
	if (luaL_dofile(L, "script.lua") ) {
		// エラー処理
		printf("%s\n", lua_tostring(L, lua_gettop(L) ) );
		lua_close(L);
		return 0;
	}

	// まず犬を生成
	lua_getglobal( L, "Dog" );					// グローバルなテーブル"Dog"をスタックに積む
	lua_getfield( L, lua_gettop( L ), "new" );	// トップに積まれたテーブルのメンバ"new"をスタックに積む
	lua_pushstring( L, "Neko" );				// 名前はNeko。犬なのにNeko。
	lua_pcall( L, 1, 1, 0 );					// 実行!
	int idx_dog = lua_gettop( L );				// Nekoのスタック上の位置を取得

	// 次に猫を生成
	lua_getglobal( L, "Cat" );					// グローバルなテーブル"Cat"をスタックに積む
	lua_getfield( L, lua_gettop( L ), "new" );	// トップに積まれたテーブルのメンバ"new"をスタックに積む
	lua_pushstring( L, "Inu" );					// 名前はInu。猫なのにInu。
	lua_pcall( L, 1, 1, 0 );					// 実行
	int idx_cat = lua_gettop( L );				// Inuのスタック上の位置を取得

	lua_getfield( L, idx_dog, "show" );	// 関数をスタック
	lua_pcall( L, 0, 0, 0 );			// 呼び出し
	
	lua_getfield( L, idx_cat, "show" );	// 関数をスタック
	lua_pcall( L, 0, 0, 0 );			// 呼び出し

    lua_close( L );	// 終了
    return 0;
}

script.lua

-- Dog
Dog = {}
Dog.new = function( name )
	local obj = {}
	obj.name = name
	obj.show = function( self )
		s = string.format( "%s the DOG.", name )
		print( s )
	end
	obj:show()
	return obj
end

-- Cat
Cat = {}
Cat.new = function( name )
	local obj = {}
	obj.name = name
	obj.show = function( self )
		s = string.format( "%s the CAT.", name )
		print( s )
	end
	obj:show()
	return obj
end

2013年8月23日金曜日

glBeginとglMaterialfvの順番とGLSLの関係

OpenGLで描画を行う際、
glBeginよりも後にglMaterialfvを呼び出すと、
シェーダーを使用した際に色が設定されない。
シェーダーを使用しなかった場合は正しく描画されてしまうのが曲者である。

// NG
glUseProgram( shaderProgram );
glBegin( GL_POLYGON );
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red );
glVertex3f( 0.0, 0.0, 0.0 );
glVertex3f( 1.0, 0.0, 0.0 );
glVertex3f( 1.0, 1.0, 0.0 );
glVertex3f( 0.0, 1.0, 0.0 );
glEnd();

// OK
glUseProgram( shaderProgram );
glMaterialfv( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red );
glBegin( GL_POLYGON );
glVertex3f( 0.0, 0.0, 0.0 );
glVertex3f( 1.0, 0.0, 0.0 );
glVertex3f( 1.0, 1.0, 0.0 );
glVertex3f( 0.0, 1.0, 0.0 );
glEnd();

shaderProgramとredは書いていないが適切な変数だと思って頂きたい。

恐らく、glBeginの時点でGPUにカラー情報が渡され、後から変更できない為に、
このような挙動になっているのではないかと。
シェーダーを使用しない場合何故通ってしまうのかは不明。

描画するオブジェクトの種類によっては、
glBeginとglEndの間で普通にglMaterialfvを呼び出すオブジェクトもあるが、
そういったオブジェクトでglBeginとglEndの間でglMaterialfvを間で呼び出すと、
シェーダーを使用する際どうなるかは調べていないので不明。
もしかしたら環境によって挙動が異なる可能性すらある。

2013年8月11日日曜日

DGZ サポートページ

DGZのサポートページです。

DGZはソースコードを公開しているフリーゲームです。
ユーザーは自由にコードを改変し、コード及びプログラムを公開することができます。
また、その際に報告の義務はありません。
ただし、コード以外のリソースは二次利用できません。
予めご了承下さい。

バグ報告・感想等は当記事のコメント欄にお願い致します。
ダウンロード

2013年7月11日木曜日

Luaの標準ライブラリのロード方法

今まで一部で躓いていたCからのLuaステートへの標準ライブラリのロードがうまくいったのでアウトプット。

以下はうまくいかないコード。
#include

int main( void ) {
    lua_State *L = luaL_newstate();
    luaopen_package( L );
    lua_close( L );
    return 0;
}

出力:
PANIC: unprotected error in call to Lua API (no calling environment)

以下が正しいコード。
#include

int main( void ) {
    lua_State *L = luaL_newstate();
    lua_pushcfunction(L, luaopen_package);
    lua_pushstring(L, LUA_LOADLIBNAME);
    lua_call(L, 1, 0);
    lua_close( L );
    return 0;
}

リファレンスを見る限りは、全てのライブラリのロードで下の方法を用いるべきと思われる。上の方法でうまく動くライブラリとそうでないライブラリが存在する。
luaL_openlibs( L ); // OK
luaopen_base( L ); // OK
luaopen_math( L ); // OK
luaopen_string( L ); // OK
luaopen_table( L ); // OK
luaopen_debug( L ); // OK
luaopen_package( L ); // NG
luaopen_io( L ); // NG
環境によるかもしれないので必ず上を使いましょう。

2013年7月10日水曜日

luaopen_mathでスタックに謎のLUA_TTABLEが積まれる件について

以下のコードは動作はするが、予期せぬ結果となる。

script.lua

function func(num)
    return num;
end

main.cpp

#include "lua.hpp"
int main( void ) {
    lua_State* p = luaL_newstate();
    luaopen_math( p );
    luaL_dofile( p, "script.lua" );
    int num = 100;
    lua_getglobal( p, "func" );
    lua_pushnumber( p, num );
    lua_pcall( p, 1, 1, 0 );
    num = lua_tonumber( p, 1 );
    lua_close( p );

    return 0;
}

最終的にnumに入っている値は100であると予想されるが、
実際には0が入っている。
luaopen_mathを呼び出した際に、謎の LUA_TTABLE がプッシュされるため、
スタックの一番下には func の返り値ではなく、
テーブルが入っており、その上に返り値が積まれている。

NG: num = lua_tonumber( p, 1 );
OK: num = lua_tonumber( p, -1 );

何が積まれているのかは調べたけど分からなかった。
誰か、Luaに詳しい方で分かる方いらっしゃったら教えて下さい。

2013年3月2日土曜日

この際だから言うけど、eneloop stick boosterはモバイルバッテリに適さない

 ここ数日eneloopのデザイン変更が世間を賑わせているeneloopを再評価する記事や、eneloopとそれらを取り巻く市場についての現状をまとめた記事は興味深い内容が多い。
 それとは別に、だいぶ前にGalaxy Nexus用の予備バッテリとしてeneloop stick booster(KBC-D1AS)を購入したのだが、思ったよりも使い勝手が良くなかったので、その理由を書いてみようと思う。
 まず、eneloop stick boosterは単体では充電できない。充電の際には中の単三電池を取り出して、充電器に接続する必要がある。シンプルな構造故取り出すのは容易だが、このちょっとした手間がそれなりにストレスになってしまう。
 次に、電池2本で3800mAhという容量は存外に少ない。10000mAh前後の安いモバイルバッテリを購入したほうが確実に良いだろう。
 そしてeneloop stick boosterには電池の残存量を知るためのインジケータが存在しない。stick booster以外ならばLEDインジケータのついた機種が存在するので、モバイルバッテリ用途ではインジケータのついた物の方が確実に良い。
 最後に、スティック型の形状は思った程のメリットは無い。アルマイトの細長いスティックというデザインは美しいが、細長い形状で大きくメリットがある人以外にとってはただそれだけだ。

 バッテリは、それが充電池であるにしろそうでないにしろ消耗品だということを実感させられた。単三電池のeneloopを買うのなら、モバイルバッテリではなくリモコン等の単三電池を使う機器で使用した方が良いし、モバイルバッテリとして使うならば容量が大きく安価な物を使ったほうが良いだろう。結局私はGalaxy Nexus用の大容量バッテリを買ってしまった。専用バッテリなら携帯電話本体を充電器として利用できるし、モバイルバッテリを接続したままで利用する煩わしさも無いので、消耗品として使い潰すには最適だと思う。ちなみに私はこのバッテリーを使用している。

 その他のGalaxy Nexus向けバッテリーモバイルバッテリー

2013年2月23日土曜日

Chromebook Pixel 発表に対する所感

 情報がリークした時、2560*1700という解像度は、たぶん2560*1600の誤りであろう、と思っていた。同じように思っていた人は少なくないであろう。Engadget 日本版の記事によれば、「ウェブやウェブアプリの使い勝手を考えて、一般的なノートの16:9や16:10より縦を広く確保したかったため」だそうだ。4年程前から徐々にWUXGA液晶が、16:9の映像を液晶面を余す事無く再生できるFullHDの液晶に淘汰されていった事を考えると、Googleのこの決断は思い切ったものだ、と思う。
 ハードウェアは、MacBook Proの13インチRetinaディスプレイモデルに極めて似ている。Intel Core i5プロセッサと、高解像度のディスプレイを搭載したモバイルノートブック、という特徴や、ラッチレス構造を採用し、シンプルでアルマイトの質感を活かした筐体のデザインはAppleに訴えられそうな程だ。もう少し詳しく見れば、液晶はMacBook Proよりも一回り小さく、重さも100gほど軽量だ。Google Driveがある代わりにSSDの容量は約半分である。MacBook Proの値段は日本では138,800円、アメリカでは1,199ドルだ。Gigazineによれば、Chromebook Pixelは1299ドル(約12万円)で販売されるらしい。全体的なスペックを鑑みるに、出来る事ならMacBook Proを切る価格で販売して欲しかった所だ(価格競争力的に)。
 個人的に注目したいのは、Chromebook Pixelのロゴのデザインだ。Appleがコーポレートフォントに採用しているMyriad Proや、MicrosoftのSegoeによく似た、モダンでシンプルなデザインのフォントで、Chromebookは細く、Pixelは少しウェイトの大きい太字のデザインだ。このフォントのウェイトは、Appleのデザインに酷似している。MacBook Airや、iPod shuffleiPod nanoiPod touchiPod classiciPad miniのロゴは、前半が太字で後半は細字だ(ちなみにiMacMacBook ProMac miniMac ProiPadOS X Mountain Lionは全体を通して太字である)。Appleのロゴについてはこちらの記事が参考になるだろう。細字と太字の順序こそ逆であるものの、そのデザインにはかなりの共通点が見られる。個人的には全体を通して同じウェイトのフォントで構成される最近のMicrosoftのロゴデザインの方が好きなのだが。

主要参考文献:

Google、2560x1700タッチ画面の Chromebook Pixel 発表。Core i5 & LTE対応 - Engadget Japanese
Googleの新型ノートPC「Chromebook Pixel」が来週から約12万円で発売、4月にはLTE内蔵モデルも - GIGAZINE
Google Chromebook Pixel
Google噂のChromebook Pixel(タッチ画面付)が流出ビデオに堂々登場
マイクロソフト、25年ぶりに新ロゴを採用。Windows 8 や Office と統一 (動画) - Engadget Japanese

2013年2月9日土曜日

DXライブラリとLuaを使ってスクリプト側で画像をロード

内容はタイトルの通り。
ソースコードは こちら 。
Lua向けに専用のLoadGraph関数を用意してやり、それをlua_Stateに渡し、
lua_State側からその関数を呼び出して画像をロードするプログラム。

コードの説明はプログラム内のコメントと、コメントに書いてあるリンク先の参考文献を参照のこと。

記事内では、プロジェクトの設定について説明する。
まず、 DXライブラリ置き場 使い方説明 に従って、DXライブラリが動くプロジェクトを作成する。
DXライブラリがうまく動いたら、 その1 Luaのインストール に従って、Luaのセットアップをする。
リンク先では、コンソールアプリケーション向けの設定についての記述なので、Win32アプリケーションで行う設定を以下に列挙する。

  1. 追加のインクルードディレクトリにluaフォルダ内のincludeフォルダへのパスを追加
  2. 追加のライブラリディレクトリにluaフォルダへのパスを追加
  3. リンカ->入力->追加の依存ファイルにlua5.1.libを追加
  4. lua5.1.dllをプロジェクトフォルダの直下にコピー
以上である。

主要な参考文献

2013年1月3日木曜日

マルチデバイスとその逆


MacBookが主流のモバイル時代、かつてApple社の救世主となったiMacを使う意味はなんだろう?!

 この記事を最近読んで思った事をつらつらと書くなど。
私も、最近この記事に書いてあることと同じ事を常々感じている。CPUは大分前から言わずもがな、最近はIntelのチップセット内蔵グラフィックスでも最低限必要十分なスペックを提供してくれる。きちんとした(あるいは内部のアーキテクチャはモバイル向けアーキテクチャでも良い)デスクトップPCの必要性を感じるのは、精々ゲームをする時や、動画のエンコードをする時くらいで、日常的な用途、ウェブブラウジングやメール、軽いゲームくらいならCore iプロセッサの最低レベルで十分こなせる。
 Windows RTがARMタブレットで動くこと等からも、Atomに代表される省電力X86アーキテクチャと、ハイエンドなARMアーキテクチャが極めて近づいてきている事がわかる。そう遠くない内に今のX86程のパフォーマンスでARM並に省電力な高効率なアーキテクチャが実現することは疑う余地が無いように思う。
 スマートフォンとPCで同じGmailにアクセスしたりするように、複数のデバイスで同じデータにシームレスにアクセスする仕組みは整いつつある。ハードウェアも同じように、タブレットコンピュータを家に持ち帰り、大きめのディスプレイやキーボードと無線でシームレスに接続して自然体で使えたりするような、複数のデバイスをシームレスに扱える時代が来るといいなぁ。