2009年12月25日金曜日

strtok_sで文字列を分割する

std::stringでは速度的に不安が出てきたのでstrtok_sを使用することにした。
strtokだとコンパイラに怒られるので、ここは素直にMSの指示に従おう。
01#include <stdio.h>
02#include <string.h>
03 
04#ifndef null_ptr
05#define null_ptr 0
06#endif
07 
08char str[] ="asdc,fghm jkl;";//分割したい文字列
09char *delim = ", ";//デリミタ(複数渡せる)ここではカンマと空白
10char *ctx;//内部的に使用するので深く考えない
11 
12//実行例
13int main()
14{
15    char *next = strtok_s(str, delim, &ctx);
16    while(next){
17        printf("%s\n", next);
18        next = strtok_s(null_ptr, delim, &ctx);
19    }
20    // 出力結果 --------------------------------
21    // >> asdc
22    // >> fghm
23    // >> jkl;
24    return 0;
25}

GUIDを生成する

インクルードガード用にGUIDを生成するデスクトップアプリを作ろうと画策中。既にいろいろ便利なものはありますが、自作ってのにこだわってみたい。車輪の再発明大歓迎。JavaでもいいけどせっかくC++メインで組んでるので頑張ってみるか…。
01#include <windows.h>
02#include <tchar.h>
03 
04#ifndef null_ptr
05#define null_ptr 0
06#endif//null_ptr
07 
08/**
09* エントリポイント
10*/
11int WINAPI _tWinMain(
12                     HINSTANCE hInst,
13                     HINSTANCE,
14                     LPTSTR,
15                     int
16                     )
17{
18    GUID guid;
19    if(SUCCEEDED(CoInitializeEx(null_ptr, COINIT_APARTMENTTHREADED))){
20        CoCreateGuid(&guid);//GUIDを生成
21        CoUninitialize();//CoInitializeとセットで必ず呼び出すこと
22    }
23    return 0;
24}
CoInitializeEx()とCoUninitialize()はセットで呼び出す必要があるそうだ。new, deleteみたいなもんか? COMコンポーネントが未だに何なのかよく分からない。DirectXAPI関数を使用している時も似たような書き方を行うものが多いが…。

ここまで書いといてなんだが、やっぱりJavaでいいような気がしてきた…('A`)
参考サイト

2009年12月22日火曜日

std::stringを分割する



レイトレーサはほぼ完成。実行速度は一気に落ちて300ms@Releaseともはやどこがリアルタイムだか分からない結果に。オブジェクト数が少ないと100msを切れるのだが、屈折・透過・鏡面反射をするオブジェクトが複数あれば計算量は指数的に増えるわけで…。とはいえそろそろフォトンマッピングが見えてきた、かな?


今日からはメタセコイアデータ(MQOフォーマット)を読み込んでレイトレーシングで描画するビューアの作成に取り掛かっている。さて、メタセコのデータを読むにあたって、テキストファイルを解釈しなければならない。そんな時にstd::stringクラスを任意のデリミタ(分割子)で分割できると便利なので、早速作ってみた。こちらのサイトが非常に参考になった。

01#include <iostream>
02#include <vector>
03#include <string>
04 
05typedef std::string String;
06typedef std::vector<String> StringList;
07 
08/**
09* 文字列を分割してコンテナに格納する
10* @param dest 分割後の文字列格納先へのポインタ
11* @param src 分割したい文字列への参照
12* @param delim デリミタ文字列への参照
13* @return 分割後の文字列格納先へのポインタ
14*/
15StringList *SpritString(
16                        StringList *dest,
17                        const String &src,
18                        const String &delim
19                        )
20{
21    String::size_type start = 0;//デリミタを検索するインデクス番号
22    while(true){
23        //デリミタが現れる最初のインデクスを求める
24        String::size_type end = src.find(delim, start);
25 
26        //デリミタが見つかった場合
27        if(end != String::npos){
28            dest->push_back(src.substr(start, end - start));
29        }
30        //デリミタが見つからなかった場合
31        else{
32            //文末までを格納して返す
33            dest->push_back(src.substr(start, src.length() - start));
34            break;
35        }
36        //次の開始地点へ移動
37        start = end + delim.length();
38    }
39    return dest;
40}
41 
42/**
43* 呼び出し側
44*/
45int main(){
46    using namespace std;
47     
48    String src("hoge piyo fuga");//区切りたい文字列
49    String delim(" ");//デリミタ(区切り文字)
50    StringList out;//区切られた文字が配列となって帰ってくる
51    SpritString(&out, src, delim);//空白文字で区切る
52     
53    //出力
54    for(String::size_type i=0; i<out.size(); ++i){
55        cout << out[i] << endl;
56    }
57    /* 出力結果---------------------------
58    > hoge
59    > piyo
60    > fuga
61    */
62    return 0;
63}
参考先のサイトでは関数内部で作成したリストオブジェクトをそのまま返していたので、軽くする目的でポインタ経由での受け渡しにしてみた。そもそも軽くしたいならstd::stringなんか使うなって話だが…。便利なんだもん。

デリミタ自体もベクタオブジェクトに突っ込んで、複数のデリミタに対応するとかいろいろ出来そう。

MQOローダ自体は以前も作ったのだが、設計が気に食わなかったので最初から作り直している。その際に『ゲームプログラマになる前に覚えておきたい技術(通称:セガ本)』の「XMLモドキを読む」という項が大変参考になった。MQOファイル自体はXML形式ではないので若干の改造が必要になるが、基本となる考え方はセガ本からまるまるパクッている。明日には完成させたい。

2009年12月16日水曜日

透過処理の実装

昨日に引き続きレイトレーシング。今日は透過処理を実装した。残念ながら屈折までは手が回らなかった、明日以降に引継ごう。屈折を行わない透過処理の場合、マテリアルの要素として環境光、拡散反射光、鏡面反射光に加えて、透過係数(transmit)を加える。
01/**
02* floatであらわされる色構造体
03*/
04struct FRGB{
05    float r,b,g;
06    static FRGB *Set(FRGB *out, unsigned char r, unsigned char g, unsigned char b);
07};
08 
09/**
10* 自作マテリアル構造体
11*/
12struct Material{
13    FRGB diffuse;//拡散反射光係数
14    FRGB ambient;//環境光係数
15    FRGB specular;//鏡面反射光係数
16    FRGB transmit;//透過係数
17};
透過係数は、0~1で定義される透明度。0の時は光を一切通さず、1の時は完全に光を通す(=透明となる)ものとする。
  1. 始点から画素方向へ向かって飛ばしたレイが、空間内に配置されたオブジェクトと衝突するかどうか調べる。
  2. 衝突しない場合は、画素に背景色を適用する。
  3. 衝突する場合は、始点に最も近い交点の座標を求め、再度交点からレイを発射する。
  4. 再発射したレイがオブジェクトと衝突している場合はここで、環境光・拡散反射光を求める。この値にレイを発射したオブジェクトの透過率を掛けて最終的な画素色とする。
以上のパターンでレンダリングした結果が以下の通り。


見事に影を落とすのを忘れてた。加えて、透過の回数を1回までとしているため、半透明のオブジェクトの先にさらに半透明のオブジェクトが存在した場合の処理が不自然になっている。画像の緑→黄色→赤の順に並んだ球体で、黄色の後ろに赤の玉が透けて見えないといけないのだが、うまくいっていない。

明日はこのあたりの改善+屈折に入っていこう。苦手な再帰呼び出しをいかに克服するかがポイントになりそうだ。

2009年12月15日火曜日

フォンシェーダの実装

今日はプラスチックや金属の光沢感を出すためのフォンシェーダにチャレンジ。


 『CによるCGレイトレーシング』によると、フォンのモデルの求め方は以下の通り。
入射光をIp
鏡面反射係数をks
レイの正反射方向と視線のなす角をa
レイの正反射方向ベクトルをL'
視線へのベクトルをV
と置いたときの表面輝度Isは
Is = ks*Ip*cosna = ks*Ip*(dot(L', V))n
となる
この時、自然数nの値を大きくすればするほど、ハイライトの広がりは抑えられて、シャープな印象になるそうです。
n=1のとき

n=16のとき



L'ってのは早い話が、ライトからの光が物体の表面に正反射した時の反射方向ベクトルですから、求め方は以下の通り。
入射ベクトルをL
表面の法線をNとすると
L' = 2*(dot(N,V))*N - L
最終的な表面の輝度は【環境光+拡散反射光+鏡面反射光】になるので、ランバートシェーダの処理のあとに上記の処理を入れるだけでフォンのモデルは実装できちゃうわけですね。

実装がお手軽なわりには、なかなか効果が出てるかなと思いました。とはいえ速度的に半分の32ms@Releaseとそろそろ不安が…。計算とか工夫すれば、まだいける…はず。

明日はいよいよ屈折をやります。

2009年12月13日日曜日

Javaでディレクトリ内のテキストファイル(*.txt)だけをリストアップする

昨日友人がやり方が分からないと嘆いていたので、ちょっと作ってみた。開発環境はnetbeans6.5.1です。
01import java.io.File;
02import java.io.FilenameFilter;
03 
04/**
05 * エントリポイント
06 */
07public class Main {
08    public static void main(String[] args) {
09        File dir = new File("C:\\");//Cドライブのルートディレクトリを開く
10         
11        //フィルタリングをかけてファイル名を列挙
12        String []files = dir.list(new MyFilter());
13         
14        //出力
15        for(int i=0; i<files.length; ++i){
16            System.out.println(files[i]);
17        }
18    }
19}
20 
21/**
22 * フィルタリングクラス
23 */
24class MyFilter implements FilenameFilter{
25    public boolean accept(File dir, String name) {
26        int index = name.lastIndexOf(".");//拡張子の"."を探す
27         
28        //"."以下の文字列を取り出して全て小文字に
29        String ext = name.substring(index+1).toLowerCase();
30 
31        //拡張子が"txt"と一致すれば取り出す
32        if(ext.equals("txt") == true) {return true;}
33 
34        //それ以外のファイルはリストアップしない
35        return false;
36    }
37}
FilenameFilterクラスは、インターフェースとして定義されておりまして、実際に使うときは自分でフィルタリングの真偽を判定するacceptメソッドを実装しなければなりません。まさに、インターフェースのお手本のようなクラスですねー。

今作ってるレイトレーサのシェーダクラスもこの作り方で切替えとかできそうです。OOPLに限らず、いろんな言語を使うことで設計について学べることがあって楽しい。関数型言語をもっと触らねばと思う今日この頃。

2009年12月11日金曜日

レイトレーシングで複数オブジェクトを描画

 昨日に続きレイトレーシングを。


今日は2種類(無限平面と球体)のオブジェクトを複数描画することにチャレンジ。Celeron 2.4GHz で平均43ms@Release と昨日の倍以上の速度で動いてくれました。Core2Duo E6600 2.4GHzでは14ms@Releaseとまだまだ余裕。

PlaneクラスとSphereクラスは共通のインターフェースObjectDataを継承しており、このおかげで当たり判定などをスマートに記述することができました。この辺はOOPLの旨みを活かせたかなと思います。仮想関数呼び出しは重いかなぁと心配だったのですが、switch文と大して速度は変わらなかったので良しとしよう。

明日は影付けですかね…。屈折やテクスチャリングなど、どんどこ重くなる要素てんこ盛りですが、30fpsはキープできるようにしたい…。

小ネタ:
空のコンストラクタはヘッダファイルに記述すると、コンパイラが最適化の際に呼び出し命令を省略してくれることもあるそうです。→参考になったサイト

2009年12月10日木曜日

リアルタイムレイトレーシング事始め

『Javaではじめるレイトレーシング入門』という面白い書籍を見つけたので、レイトレーシングに挑戦。大まかな仕組みをつかんだところで、C++で書き起こしてみることに。先生にお借りした『CによるCGレイトレーシング』がかなり参考になった。

とりあえず、カメラとスクリーンはワールド空間に固定して、球体を描画。シェーディングはランバートで。画素数は500*500です。



我が家のポンコツマシン(Northwood Celeron 2.4GHz)で実行したところ、Debugで600ミリ秒、Releaseで93ミリ秒というなんとも情けない結果に終わった。FPS換算だと1~10FPSとかちょっと…。というかまだオブジェクト1個だし、屈折とかテクスチャリングとかやってないし!

言い訳すると有り合わせのクラスをパチ組みしただけなので、無駄な呼び出しというか、OOPっぽい書き方になってるのが遅れの原因か。ローカルに作ったワーク変数が、空のコンストラクタを呼び出してたりいろいろ無駄がありそう。

とはいえ、一番の原因はアルゴリズム部分でしょうね。きっとまだ無駄な判定やってるに違いない、今から見なおそう。

TODO:
飽和加算とか。

<追記 2009.12.10@2:10am>
320*240で10fps@Debug, 60fps@Releaseを達成できました。
500*500は3fps@Debug, 13fps@Releaseが今のところ限界…。

ベクトルの正規化がかなり足を引っ張っていたようです。0割防止のため、ノルムが0の時は割り算を行わないという処理をやっていたのですが…。
01Vector3 &Vector3::normalize()
02{
03    float len = x*x+y*y+z*z;//ノルムの平方
04    //以下len = sqrt(len);と同じ
05    __asm{
06        fld len
07        fsqrt
08        fstp len//お行儀が悪いがlenを使いまわす
09    }
10 
11    //0割防止
12    if(len < FLT_EPSILON){
13        x=y=z=0;
14    }
15    else{
16        float denom = 1.f / len;
17        x *= denom;
18        y *= denom;
19        z *= denom;
20    }
21    return *this;
22}
上記のif文の評価式をlen >= EPSILONにして、ブロックを入れ替えた方がジャンプが減る分確率的に速くなる…気がする。てかここでごっそり速くなった。
1if(len >= FLT_EPSILON){
2    float denom = 1.f / len;
3    x *= denom;
4    y *= denom;
5    z *= denom;
6}
7else{
8    x=y=z=0;
9}

2009年12月3日木曜日

SLAX覚え書き

今できること
  1. CDからSLAXを立ち上げる
  2. USBを手動でマウントして、WLANドライバをndiswrapperにインストールする
  3. ndiswrapperを手動で実行する
  4. HDDを汚さないお手軽自宅サーバの完成(・▽・)

TODO:
  1. USBドライブのマウントを自動化
  2. 無線LAN子機の認識までの設定をUSBに保存しておく

上記を達成するには
  1. Linuxのコマンドの基本的なところをしっかり学習
  2. Windowsでいうbatファイルに当たるshファイルの作成を勉強しなくては…

2009年11月24日火曜日

fsincosでプチ高速化

ここ最近、透視投影行列についてお勉強していました。透視投影行列を求めるために、D3DXMatrixPerspectiveFovLH()関数と同じ機能を持つ関数を自前でこしらえるとなると、どうしても速度的に問題が出てきます。

MSDNによるとD3DXMatrixPerspectiveFovLH()関数の中身は以下の通り。
w       0       0               0
0       h       0               0
0       0       zf/(zf-zn)      1
0       0       -zn*zf/(zf-zn)  0
where:
h is the view space height. It is calculated from 
h = cot(fovY/2);

w is the view space width. It is calculated from
w = h / Aspect.
ここで問題になるのがcot(fovY/2)の部分。コタンジェントは tanθの逆数らしいので、つまるところcosθ/sinθ。

毎フレーム呼びたい関数にsin()とcos()関数が両方とも入っちゃってるわけです。実際、素直に書き起こしたコードとD3DXMatrixPerspectiveFovLH()関数の速度を比較してみたら、1000万回のループでおおよそ1.5~2倍くらいの時間差が! ボトルネックは予想通り、sin()とcos()でした。

そこでsin()とcos()の部分だけインラインアセンブラで高速化に挑戦してみることにしました。 使った命令は8087命令セット?なので、まあ今日のx86プロセッサなら問題なく使えると思います。

ただ、この8087命令は使用するレジスタがちと特殊なようで、汎用レジスタからではfsincos命令の引数も戻り値も受け取ることはできないっぽい。長々と書くのもアレなんで、ズバリ答えが載ってるサイトを発見しました。ありがたく利用させていただくことに。

1float angle, cosx, sinx;//引用元はdoubleでしたがfloatに変更させていただきました
2_asm
3{
4 fld angle ;レジスタスタックに角度をプッシュ
5 fsincos  ;fsincos命令で一気にsin(angle)とcos(angle)を計算。答えはST(0)にcos,ST(1)にsinが入っている。
6 fstp cosx ;ST(0)スタックトップからcosをポップ。ST(1)がST(0)にスライドする。
7 fstp sinx ;同じくスタックトップからsinをポップ。
8}

たったこれだけのコードで、sinθとcosθの値が同時に求められるんですね。これは便利だ。速度もd3dxをぶっちぎりで上回る200%以上の効果。ここまで速いと、エラーチェックとか要るのかなぁとかえって不安になってしまいますが…。まぁ気にしない気にしない…。

 とっても参考になったサイト
SSE2を用いたPOV-Rayの最適化に関する考察
Intel x86 Instruction Reference
SIMPLY FPU

2009年11月17日火曜日

operator<<のオーバーロード

またハマってしまった…。環境はVC++2008です。

ある名前空間内で宣言されたクラスにおいて、operator<<をオーバーロードして標準出力にクラス内の情報をを出力したいと思ったわけですよ。

コードにするとこんな感じ。

01namespace hoge
02{
03class aho
04{
05public:
06  friend std::ostream &operator<<(std::ostream &os, const aho &a);
07};
08}//!hoge
09 
10//以下の記述(というか記述場所)が誤り
11std::ostream &operator<<(std::ostream &os, const hoge::aho &a)
12{
13    return os << "aに関係した何か";
14}


ここでなにを勘違いしたのか、私は上記の関数の実装をグローバル空間で行ってしまった。結果は当然、

namespace.cpp(20) : error C2593: 'operator <<' があいまいです。
namespace.cpp(12): 'std::ostream &operator <<(std::ostream &,const hoge:
:aho &)' の可能性があります。
namespace.cpp(6): または 'std::ostream &hoge::operator <<(std::ostream &,const hoge::aho &)' [引数依存の照合を使用して検出しました] の可能性があります
引数リスト '(std::ostream, hoge::aho)' を一致させようとしているとき
 そんな関数ありませんよ、と怒られてしまった。

こんなアホな間違いをする人間はなかなかいないようで、ググってもそれらしき解決策は見当たらない。が、世界レベルだと同じことをやらかす方もいらっしゃるようで、ようやく解決。

早い話が、hogeという名前空間内で宣言したクラスにおいてfriend関数を宣言したならば、その実装もhogeの中でやれってことだそうです。以下ちゃんとコンパイルできたコード。

01namespace hoge
02{
03class aho
04{
05public:
06    friend std::ostream& operator<<(std::ostream &os, const aho& a);
07};
08 
09//hogeの中で実装するのが正解
10std::ostream &operator<<(std::ostream &os, const hoge::aho &a)
11{
12    return os << "('A`)";
13}
14}//!hoge
言い訳ではないですが、operator<<ってなんかグローバルな演算子な気がしてですね…。そのくせ、普段operator=とかoperator*とかは平気でメンバ関数として実装してるわけですが…。自分のアホさに辟易させられた小一時間でした。こんなミスする人は滅多にいないでしょうが、何かの役に立てば幸いです…。

2009年11月15日日曜日

VC++でインラインアセンブラ

おもろそうな記事を見つけたので試してみた。
生でアセンブル言語を使用するのはちと敷居が高いので、インラインアセンブラから入ってみようという企画。ゆとりPGの自分にはちょうどいい。

用語の整理
  • ロード メモリからレジスタに値を読み込むこと
  • ストア レジスタの値をメモリに書き込むこと
  • 汎用レジスタ いろんな計算に使える便利なやつ。EAX~EDXまであるようだ

とりあえず実践。出力は普通にcoutを使うよ。
01#include <iostream>
02using namespace std;
03// iに100を代入して表示するだけのプログラム
04int main()
05{
06    int i;
07    __asm
08    {
09        mov i, 100;
10    }
11    cout << i << endl;
12}
次にレジスタを使ってみる。
01#include <iostream>
02using namespace std;
03// レジスタに0xFFFF0000をロードしてiにストアするプログラム
04int main()
05{
06    int i;
07    __asm
08    {
09        mov eax, 0xFFFF0000;
10        mov i, eax;
11    }
12    cout << hex << i << endl;// ffff0000
13}
配列を扱うときは、インデクスの値に注意。インデクスを1つ増やしてもアセンブラでは1バイトしか移動しないようだ。そこで、Cでいうところの[sizeof(int)]と同じ役割を持つ[type 変数名]をインデクス値にかけてやる必要がある。
01#include <iostream>
02using namespace std;
03//配列arrayに値を代入するプログラム
04int main()
05{
06    int array[4];
07 
08    __asm
09    {
10        mov array[0], 100;
11        mov array[1*type array], 200;//1*sizeof(int)と同じ。これでポインタが4バイト移動する
12        mov array[2*type array], 300;
13        mov array[3*type array], 400;
14    }
15  
16    for(int i=0;i<4; ++i)
17    {
18        cout << "array[" << i << "] = " << array[i] << endl;
19    }
20    return 0;
21}

みんな大好きポインタ篇
01#include <iostream>
02using namespace std;
03int main()
04{
05    int i;
06    int *p = &i;//pにiのアドレスを格納
07    __asm
08    {
09        mov ebx, p;ポインタ用のレジスタEBXにpをロード
10        mov [ebx], 100;*pに100をストア
11    }
12    cout << i << endl;//100
13    return 0;
14}

ポインタが指す実体を参照したい場合は、レジスタ名を[]で囲むといいようだ。ポインタ変数pに対する*pと同じことが、レジスタEBXに対する[EBX]で行えるというわけだ。

なお、__asmブロック内ではC/C++のコメント//や/**/が使えるほか、;の後ろも1行コメントとして認識されるらしい。

構造体も扱えちゃう
01#include <iostream>
02using namespace std;
03//適当に構造体を作成
04struct FOO
05{
06    int val1, val2;
07};
08 
09int main()
10{
11    FOO a;//実体を作る
12    FOO *p = &a;//aへのポインタ
13    __asm
14    {
15        mov ebx, p//aのアドレスをレジスタEBXにロード
16        mov [ebx]a.val1, 100/*ポインタを参照してa.val1に100をストア*/
17        mov [ebx]a.val2, 200;同様にa.val2に200をストア
18    }
19    cout << "a.val1 = " << a.val1 << endl;// a.val1 = 100
20    cout << "a.val2 = " << a.val2 << endl;// a.val2 = 200
21    return 0;
22}
次回は演算を勉強しよう…

2009年11月14日土曜日

templateクラスでoperator<<をオーバーロード

templateクラスHogeのインスタンスfugaを、
1Hoge<int> fuga;
2std::cout << fuga << std::endl;
みたいに出力しようと思えばoperator<<をオーバーロードする必要があります。
んで、
01#include <iostream>
02using namespace std;
03 
04template<class T>
05class Hoge{
06public:
07    friend ostream &operator<<(ostream &os, const Hoge &h);//decl※実はここが間違い
08   T elem;
09};
10//impl
11template<class T> ostream &operator<<(ostream &os, const Hoge<t> &h){
12    return os << h.elem;
13}
とか書いてみたところ見事にリンクエラーを食らってしまった。
error LNK2019: 未解決の外部シンボル "class std::basic_ostream<char,struct std::char_traits><char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits><char>> &,class Hoge<int> const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABV?$Hoge@H@@@Z) が関数 _main で参照されました。
要するにヘッダに宣言したoperator<<(declのところ)と、実装したoperator<<(impl)が別物だと解釈されているようだ。

色々試してみたところ宣言部に間違いがあったようで、正しくは以下のようになります。
1template<class T>
2class Hoge{
3  //関係ないところは省略
4  friend ostream &operator<<<T>(ostream &os, const Hoge &h);
5};
ほとんどの部分が一緒なんですが、よーく見てみると、operator<<の後ろに<T>なる文字が入っています。マジわかりづらい。

テンプレートは便利なんですが、私のような素人にとっては大変な危険も伴う諸刃の剣のように思えてなりません。てか素直にtoStringメソッドでも作ったほうがよかったのかもしれん…。

どうでもいいがこの記事書くのに異様に時間がかかってしまった。理由はエスケープ文字。<やら>やらがたくさん出てくるおかげで&lt;なんかをあちこちに書かなきゃいかんかった。今度からここを使おう
HTMLエスケープ(HTMLエンコード)ツール

2009年11月12日木曜日

Pythonでソースのエンコードを指定する方法

Pythonのコードを書いているとき、日本語でコメントをつけた部分にエラーが出て怒られた。
おそらくエンコードの指定が不正、もしくは不明なのが原因だと思われる。

こいつに対処する方法はソースコードの文頭に、以下の記述を行えば良いようだ。

1# -*- coding: mbcs -*-
Windowsならたいていはこれで大丈夫?

参考

2009年11月9日月曜日

Syntax Highlighter

ブログなどで見かけるソースコードが綺麗に表示されてるあれです。

色々やってみたのに最終的にウィジェット追加ボタンをクリック一発ポンだったとは…。

テストも兼ねてトライ
1/**
2 * test
3 */
4char *test()
5{
6    return "aho";
7}
こりゃ便利だ。晒す価値のあるコードが書けるかどうかは別として…。

さらに詳しい情報 

2010/06/02追記
上記のSyntaxHighlighterのバージョンは1.5だったのですが、2.0をBloggerで使用する方法が下記のサイトに掲載してありました。
Awesome code syntax highlighting made easy | Carter Cole's Blog

タグ付けの方法がちょっとだけ変わった
class = "cpp"  -----------> class = "brush: cpp"
ので注意!
結局ブログの全記事のHTMLソースを書き換えるはめになった。

2009年11月7日土曜日

チュートリアル動画

ニコ動にBlenderのチュートリアル動画 が上がっていた。これは…ありがたい…。
基本的なことから解説してくれているので、まさに今の自分にぴったり。

Blender導入

我が家のマシンにBlender2.49bが入った。オランダ発のフリー3DCG開発環境だそうで、優れた機能と変態的なUIを持つことで有名、だそうだ。

以下にWindowsXP32bitでの導入手順を示す。

1.Python2.6を入手する(任意)


これがないと動かないので、Python2.6以降を入手しよう。
プラグインが動かなくなるだけで、必須ではないようです。まあでも、あった方が色々便利だと思う。
http://www.python.jp/Zope/download/pythoncore
現在最新版は2.6.2のようなので、インストーラ付きのpython-2.6.2.msiを選択。

2. Blender2.49bを入手する


http://www.blender.org/download/get-blender/
windows使ってるなら、windows32bitsを選択すればおk。

Python、Blenderの順にインストールしていく。とりあえずこれでインスコは完了。あとはBlenderの日本語化と簡単な設定変更。

3.Blenderの日本語化

Blenderを立ち上げたら、画像の部分を引っ張って設定パネルを表示する。

1.Lauguage&Fontのタブを選択。
2.SelectFontでフォントを選択する。
デフォルトだとC:\WINDOWS\Fonts\あたりにフォントは入ってるんじゃなかろうか。ディレクトリ操作がWindowsとはかけ離れているので注意。上の階層に上がるときはPボタンを押し、決定はダブルクリックではなく、ENTERキー押下だということに気をつけよう。

3.Language:Englishとなっている部分をクリックして、Language:Japaneseを選択。下にある3つのボタンを押せば日本語化は完了。最後にCtrl+Uを押して設定の変更を保存しておこう。これを忘れると次回起動したときにまた同じことをやるハメになる。

以上、導入と簡単な設定について書いてみた。

備忘録がわりに

主にプログラミング・3DCGのことでも書いていこうか。