まどかの 日記

[2001/10/13〜2001/10/21の日記]
[2001/10/22〜2001/10/28の日記]
[2001/10/29〜2001/11/04の日記]
[2001/11/05〜2001/11/11の日記]
[2001/11/12〜2001/11/18の日記]
[2001/11/19〜2001/11/25の日記]
[2001/11/26〜2001/12/02の日記]
[2001/12/03〜2001/12/09の日記]
[2001/12/10〜2001/12/16の日記]
[2001/12/17〜2001/12/23の日記]
[2001/12/24〜2001/12/30の日記]
[2001/12/31〜2002/01/06の日記]
[2002/01/07〜2002/01/13の日記]
[2002/01/14〜2002/01/20の日記]
[2002/01/21〜2002/01/27の日記]
[2002/01/28〜2002/02/03の日記]
[2002/02/04〜2002/02/10の日記]

0128
2002/02/17()
 P/ECEユーザ ひとり増えました 
 今日は毎週恒例の彼女と遊ぶ日でした。

 で、今日は彼女がちょっとP/ECEに興味を持ったので、これは良い機会だと、先日買っておいたP/ECEを彼女にプレゼントし、P/ECEユーザを一人増やすことに成功しました(^^;
 
 彼女はプログラムがあんまり得意じゃないので(VBはできますが)おそらく、MMLで音楽を打ち込んだり、ちょっとしたCGを描いたりすることに専念すると思います。

 一応MM音楽館の壁紙機能お披露目用のサンプル壁紙も頼んでるので、そのうち彼女の作品が皆さんのお目にかかる日が来ると思います。

 で、今日はこの前YAHOOオークションで手に入れた、ファミコンの「ソロモンの鍵」・「ドルアーガの塔」・「不動明王伝」・「燃えろプロ野球(黒)」で遊んだ後、スマブラDXで楽しみました。

 それにしてもスマブラDXは色んなものが詰め込んであって飽きませんねぇ(^^; いやぁすごい。

 そして、部屋に帰ってからは、P/ECE改造の準備として、P/ECEを開けて外部端子の5番にかぶっている液晶押さえフレームの様子を確認してみましたが、接着剤かなんかでしっかり固定されているため、これを削るのがちょっと難しそうです。
 ためしに、手持ちのカッターで削ろうとがんばってみましたが、カッターナイフでプラスティックを切るのは骨が折れそうです(^^;

 というわけで、プラスティックを削るために、なんか工具が必要になりました。
 で、ちょっとネットで調べたところ、どうも小さいのこぎりや、電動のリュータという工具が良さそうな感じです。
 でも、リュータは高そうなので、とりあえずプラモデル用の糸ノコとかを購入して、再度チャレンジしてみようと思います。
 ここらへんの情報は模型やフィギュアを扱っているページでよく紹介されているようです。
 
 ああ、なんかだんだん色んな工具が増えていくなぁ。なんとかこれ一回で使うのが終わりにならないように、他にもなんか作らないとねぇ。
 そうそう、この前ちょっと大須の第2アメ横で電子工作のキットをチラッと見たけど、すごいちっちゃいケースのものが数千円したのには驚きました。そのキットを買ってもできることといったら、マイクの音量を大きくするアンプとかたいていひとつの機能のみで、このためだけに数千円かけるのはちょっと学生さんとかにはできないなぁと思いました。

 こんなに高いと電子工作に興味を持った小学生や中学生がなんか作りたいと思っても手が出せないよね。
 しかし、ここら辺のことをうちの会社のハード部門の人に聞いたら、「キットは作ったことない」との返事が帰ってきたので、もしかしたらこの値段の高さが、なんとか工夫をして自分で創ることを憶えさせることに役立っているのかもしれません。うーん、やっぱり違うかなぁ(^^;

 とにかく、キットは高いのでなんとかして欲しいものですね。でも、基盤の原価が高いからしょうがないのかもしれませんね。

 というわけで、なんか私もソフトの世界から、ハードの世界に足を踏み入れようとしています。
 もともと、工作することは大好きなので、今からちょっと楽しみです(^^;

 それでは、今日はこの辺でおやすみなさい。

0127
2002/02/16()
 P/ECE改造 壮大な計画で 
 えー、今日はお昼まで十分睡眠をとったあと、部屋の片づけをちょっとしてから、大須にお買い物に出掛けました。

 今日のお買い物の目的は、「P/ECEにカメラを取り付けるための部品集め」です。
 先日2/9に行われたP/ECEのオフ会でetoさんという方が見せてくれた、カメラ付きのP/ECEを見て、どうしてもやりたくなった私は、改造するための部品を探しにいくことにしました。

 ちょっと具体的に言いますと、feelH''用のカメラ(Trevaといいます)をP/ECEの外部端子につなげることによって、カメラから画像を取得しようというものです。

 とりあえずもうやった方がキャプチャソフトのソースも公開されているので、私がやることといえば、カメラをつなぐための筐体改造といったとこですが(^^;

 で、そのための部品ですが、とりあえずカメラがないと話にならないので、feelH''を扱っているショップでTrevaを探し、購入しました。約4000円でした。
 ちなみに、どうもこれを使う人がほとんどいないらしく、どこ行っても在庫がなくて、やっとのことで見つけました(^^; また、色はシースルーじゃない方が良かったのですが、1つしかなかったので、仕方なくホワイトのシースルーです。

 次に、カメラをつける部分の部品を探します。feelH''ではイヤホンをつける穴にカメラをさすことで、カメラからの映像を取り込むことができるので、部品としてはイヤホンのピンをさす穴がついたものなのですが、この部品がちょっと特殊で、この部品だけではどうも市販されていないようです。

 そこで、今日はfeelH''の展示用模型(モックアップと言うそうです)を探すことにしました。普通のモックアップにはイヤホン端子などの部品がついていることはないのですが、feelH''の場合、カメラを付けて展示する場合に必要なので、PanasonicのfeelH''のモックアップには、なんとこの部品が付いているのです(^o^

 これもなかなか見つけることができなかったのですが、ようやくこのモックアップを売っている店を発見し、1個100円(安い(^^;)でとりあえず5つ程購入しました。
 あとは、この部品をP/ECEの外部端子に繋げれば、改造完了です。でも、そのまま取り付けると、カメラ専用の改造になってしまうので、とりあえず外部端子を外に出すようにして、そこにイヤホン端子部品を取り付けられるような簡単な基盤を作っての接続にしようと考えています。
 
 今日は、その他作業に必要な半田ゴテや、テスター、ニッパー、ラジオペンチなどを購入しました。
 こういう改造作業は初めてなので、道具を集めるだけでも結構お金がかかってしまいました(−−;
 でも、まあ、最初だけだし、勉強のためなので、お金がかかるのは良しとします。


 で、ここからは私の壮大な改造計画を記します。
 その名も「P/ECEで車を走らせよう!!計画」です(^^;

 具体的に言いますと、カメラ付きのP/ECEを、ラジコンカーのようなバッテリとモータとステアリングサーボを備えている車に取り付けて、カメラからの映像の変化をもとにモータとサーボを制御して、車を動かそうという利用価値ゼロな計画です(^^;

 車の操作はカメラに向かって、たとえば手を振ったりしてカメラの画像を変化されることで実現し、前のフレームの画像と比較して、画像の上部分が激しく変化していれば前進し、下部分が変化していれば後進といった感じで操作します。いちおうサーボも制御して画面の右部分が変化したら、ステアリングを右にきるなどして、カーブさせたりしたいのですが、カーブするとカメラが操縦者の方を向かないのでダメかもしれません(^^;
 (根本的に、車が走ると画面全体が変化するので、そもそもこういった操作は無理かもしれませんが)

 これはあくまでたとえばの話で、もしかしたら実現不可能かもしれませんが、とにかくカメラからの映像で車を動かすというコンセプトで(^^
 できれば、手を振ることで操作がしたいんですが、床に線を描いて、カメラでそれを追従して線に沿って動くとか、コースに矢印の札かなんかを置いておいて、それで動かすとか、そんな方法でも操作できるかなぁ。
 ま、車の操作方法は、画像処理するソフトの方で決まるので、その時になったら良い方法を考えることにしよう。

 それから、モータやサーボの制御は、H8などのマイコンを使って実現し、P/ECEからは1ビットの出力ポートを使ってシリアルでコマンドを送り、”1”だったら前進のモータ制御、”2”だったら後進のモータ制御、”3”だったら右へのステアリングサーボ制御といった形でやろうと考えています。
 そのためには、制御用のH8のファームも書かないといけませんが、そこらへんは仕事でもやっているので、まぁなんとかなるでしょう(^^; H8用の電源はラジコンのバッテリから供給する予定です。

 とりあえず、カメラで車を動かすのが目標ですが、カメラからの画像を何秒かごとにファイルに保存しておき、走行後にその画像を取り出して、パソコンでアニメーション表示してみるなど、アイディアはいっぱいあります。車載カメラの映像だからおもしろそうだよね。

 とまあ、いろいろ書いてみましたが、まずはP/ECEの外部端子を外に出さないと何もできないので、それをやろうと思います。中の液晶押さえのフレームを少し削ったり、絶縁フィルムを少しカットしたり、ケースをちょっと切ったりしないといけないので、いきなり多くの関門が待ち受けていますが、ゆっくりマイペースでやっていきたいと思います。目標は、今月中にP/ECEにカメラを取り付けるまでをやりたいです。

 その後は、いきなり長期の研究になって、モータやサーボの制御方法を調べたり、ベースとなるラジコンカーを調査したり、H8のマイコンボードを買って、ファームを組んだり。やることたくさんです(^^;
 やっているうちに、意欲が萎えないようになんとかがんばりたいなぁ。

 ちょっと本で調べたら、モータにもいろいろ種類があって、ただ回すだけなら電池を繋げれば良いだけだけど、回転速度や回転方向を制御しようと思ったら、制御用の回路をつけないといけないみたいだし。昔ラジコン作ってた頃はそんなこと1ミリも考えたこと無かったけど、結構成業するって大変なんだねぇ。

 というわけで、これからはMM音楽館を作りつつ、MMLで音楽も打ち込みつつ、P/ECEで車を動かすことを目標にがんばりたいと思います。

 それでは、今日はこれでおやすみなさい。

0126
2002/02/15()
 できました。DirectX8.1でアンチエイリアス付き文字描画 
 えー、なんか長いタイトルになってしまいましたが、タイトルの通り、今日DirectX8.1でGetGlyphOutlineを使ってのアンチエイリアス付き文字描画ができました。
 この文字列描画のメリットは、画面のプロパティの効果タブの中にある、「スクリーン フォントの縁を滑らかにする」のチェックに左右されず、アンチエイリアス付きのキレイな文字を描画できることです。

 DirectX8になって、DirectDrawがDirect3Dと統合されて、DirectGraphicsとなったときに、テクスチャ(サーフェス)のデバイスコンテキストのハンドルを取得することができなくなり、テキスト描画APIを使っての文字列描画が容易にできなくなりました。

 で、DirectX8で画面に文字を描画するにはどうすればよいかといいますと、やり方はいろいろありますが、まず一番簡単なのがD3DXFontを使っての描画です。D3DXCreateFontIndirectなどでID3DXFontオブジェクトを作って、それのDrawTextメソッドを使えば、めちゃ簡単に文字列描画ができますが、簡単な分めちゃ遅いです。

 画面に小さい文字を数文字出す程度なら問題ないかもしれませんが、アニメーションしている画面に文字列を出す場合にはまず遅くて使い物になりません(^^; FPSが半分くらいに落ちてしまいます。

 で、この遅さを克服するためによく使われるのが、テクスチャと同じ大きさのDIBセクションを作って、そこに文字列を描画してテクスチャに転送する方法。
 この方法だと、速いのですが、ひとつ問題がありまして、画面のプロパティの効果タブにある「スクリーン フォントの縁を滑らかにする」にチェックが入っていると、TextOutAPIで描画した文字に勝手にアンチエイリアスがかかってしまい、DIBの背景色と半透明合成されるため、テクスチャにして画面に表示したときに、文字の縁が変な色になってしまいます。かといって、「スクリーン フォントの縁を滑らかにする」のチェックを外して描画した場合、文字の縁はギザギザのままなので、見た目に美しくありません。

 では、どうすればキレイな文字を速く描画できるのでしょうか。
 というわけで、今回はGetGlyphOutlineを使った文字描画を紹介します。

 この方法を使うと後ろのイメージと半透明で合成されたアンチエイリアスで文字をキレイに描画することができます。速度はDIBに描画して転送する方法より劣りますが、D3DXFontを使うよりはかなり速いです。

 では、実際に描画した画面を見てみましょう。
 
 
 <画面の説明>
 3Dに非力なIntel 815でウインドウ表示させているので、FPSが35とかになっています。
 うしろでは立方体の3Dオブジェクトに適当なテクスチャを貼り付けて、半透明な板と一緒にグリグリ回しています。
 また、文字の色は頂点色を利用ているので、グラデーション表示も可能です(^^;
 画像はpngです。

 どうです? キレイに描画されてますよね? 
 それでは、アンチエイリアスがかかっているのを確認してもらうために、拡大表示してみます。

 
 
 文字のアンチエイリアス色が背景の青と半透明合成されているのがわかるでしょうか。
 ちなみに↑の画像は、2つの文字列の間を縮めてあります。

 この描画では、GetGlyphOutlineにGGO_GRAY4_BITMAPを指定して、17段階のアンチエイリアスがかかるようにしています。

 はい、実際に描画されている画面を見てもらったところで、ちょっとわかりにくいソースを公開しますね(^^;
 今回は文字列描画ルーチンをDLL化して実装しているので、DLL用の記述が入っていますが、結局は1つの関数なので、よく見ればわかってもらえると思います。

 それでは、ずらずらーっと公開です(^^;

※参照しているヘッダーファイル内で定義されている内容です
//---------------------------------------------------------------------------
//■■ 構造体 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
//---------------------------------------------------------------------------
// トランスフォーム済み頂点
struct D3DTLVERTEX
{
        float x,y,z;
        float rhw;
        DWORD color;
        float tu0,tv0;
};

#define D3DFVF_TLVERTEX (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1)

※DLL実装部です(一部省略しています)

#include <mbstring.h>       //_mbsnextc / _mbsinc用
//---------------------------------------------------------------------------
//■■ 定数定義 ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
//---------------------------------------------------------------------------
#define PLANE_WIDTH     1024    //文字描画プレーンの幅
#define PLANE_HEIGHT    64      //文字描画プレーンの高さ

#define MOJI_SIZE       64      //デフォルトの最大文字サイズ                            
//---------------------------------------------------------------------------
//■■ グローバルオブジェクト ■■■■■■■■■■■■■■■■■■■■■■■■
//---------------------------------------------------------------------------
BYTE                    *g_pDIB = NULL;    //DIBデータへのポインタ
BYTE                    *g_pMoji = NULL;   //1文字描画用バッファへのポインタ
DWORD                   g_dwBuffSize = 0;  //1文字描画用バッファの最大サイズ
HDC                     g_hDC = NULL;      //メモリDCのハンドル
LPDIRECT3DTEXTURE8      g_pMojiTex = NULL; //文字描画用テクスチャ

//---------------------------------------------------------------------------
//■■ 関数インプリメント ■■■■■■■■■■■■■■■■■■■■■■■■■■
//---------------------------------------------------------------------------
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved )
{

    //DLL エントリ

    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:

                //初期化処理
                CreateMojiBuffer();

                break;

        case DLL_PROCESS_DETACH:
                
                //終了処理
                ReleaseMojiBuffer();

                break;

        case DLL_THREAD_ATTACH:
        
        case DLL_THREAD_DETACH:

                break;
    }

    return TRUE;

}
//---------------------------------------------------------------------------
void CreateMojiBuffer(void)
{

        //初期化処理

        //PLANE_WIDTH * PLANE_HEIGHTの16bitDIBを作成する

        //メモリデバイスコンテキストを作成
        g_hDC = CreateCompatibleDC(NULL);

        //文字描画領域の作成
        g_pDIB = new BYTE[PLANE_WIDTH * PLANE_HEIGHT * 2];
                
        //1文字描画用バッファの最大サイズを算出
        g_dwBuffSize = MOJI_SIZE * MOJI_SIZE;

        //1文字描画用バッファの作成
        g_pMoji = new BYTE[g_dwBuffSize];
        
}
//---------------------------------------------------------------------------
void ReleaseMojiBuffer(void)
{

        //終了処理

        //テクスチャの削除
        if(g_pMojiTex != NULL)
                g_pMojiTex->Release();

        //メモリDCの削除
        DeleteDC(g_hDC);

        //DIBの削除
        if(g_pDIB != NULL)
                delete[] g_pDIB;
        
        //1文字描画用バッファの削除
        if(g_pMoji != NULL)
                delete[] g_pMoji;

}
//---------------------------------------------------------------------------
DRAW_API HRESULT __stdcall PlugInDraw(LPDIRECT3DDEVICE8 lpD3DDevice,
                                      float fParam1,float fParam2,DWORD dwParam3,
                                      RECT rcParam4,void *pParam5,void *pParam6)
{

        //描画系プラグイン
        //画面にテキストを描画
        
        //パラメータ内訳
        //(パラメータの内容は自由に決めてください)
        //fParam1       X座標(とりあえずピクセル単位で)
        //fParam2       Y座標(とりあえずピクセル単位で)
        //dwParam3      文字色(α値付き)
        //rcParam4      描画領域
        //pParam5       LOGFONT構造体へのポインタ
        //pParam6       NULLで終わる文字列へのポインタ
        //
        //rcParam4が(0,0,0,0)の場合、fParam1,fParam2の
        //位置に描画します


        LOGFONT *pLogFont = NULL;       //フォント情報
        LOGFONT logfont;
        TEXTMETRIC tm;                                  
        HFONT hFont = NULL;             //フォントハンドル
        HFONT hOldFont = NULL;          //以前のフォントハンドル
        BYTE *pMoji = (BYTE*)pParam6;   //文字列へのポインタ
        UINT uChar;                     //文字整数値(1文字分)
        SIZE size;                      //描画領域のサイズ
        int mw,mh;                      //文字の幅と高さ(1文字分)
        int offset_x = 0;               //左上位置からのオフセット
        int offset_y = 0;
        int dstx = 0;                   //描画先X座標
        GLYPHMETRICS GlyphMetrics;      //文字のグリフ情報(?)
        DWORD dwBuffSize;               //必要なバッファのサイズ
        MAT2 mat2 = {{0,2},{0,0},{0,0},{0,1}};  //文字の描画用行列(なぜか横に2倍しないとだめ)
        WORD Alpha;                     //アンチエイリアスのα値
        int x,y;
        DWORD dwMAGFILTER;              //テクスチャステージ情報
        DWORD dwMINFILTER;                              
        DWORD dwCOLORARG1;                              
        HRESULT ret = E_FAIL;           //戻り値
        

        //フォント情報があるか?
        if(pParam5 == NULL)
        {

                //無い場合は、"MS ゴシック"の12ポイントフォントにする
                logfont.lfHeight         = 12;                          //ポイント
                logfont.lfWidth          = 0;                           //幅(0:だと自動設定)
                logfont.lfEscapement     = 0;                           //テキスト行の描画角度
                logfont.lfOrientation    = 0;                           //ベースラインの角度
                logfont.lfWeight         = 400;                         //文字の太さ(400:標準 700:太字)
                logfont.lfItalic         = FALSE;                       //斜体指定
                logfont.lfUnderline      = FALSE;                       //下線付き指定
                logfont.lfStrikeOut      = FALSE;                       //打ち消し線指定
                logfont.lfCharSet        = SHIFTJIS_CHARSET;            //文字セット指定
                logfont.lfOutPrecision   = OUT_DEFAULT_PRECIS;          //フォントの出力精度指定
                logfont.lfClipPrecision  = CLIP_DEFAULT_PRECIS;         //クリッピング精度指定 
                logfont.lfQuality        = DEFAULT_QUALITY;             //フォントの出力品質指定
                logfont.lfPitchAndFamily = DEFAULT_PITCH;               //フォントのピッチ指定
                strcpy(logfont.lfFaceName,"MS ゴシック");             //フォントの書体名指定

                //ポインタを設定
                pLogFont = &logfont;

        }
        else
        {

                //フォント情報へのポインタを取得
                pLogFont = (LOGFONT*)pParam5;

        }

        //フォントの作成
        hFont = CreateFontIndirect(pLogFont);

        //フォントが作成できたか?
        if(hFont != NULL)
        {
                
                //フォントをメモリDCに登録
                hOldFont = (HFONT)SelectObject(g_hDC,hFont);

                //現在のフォント情報を取得
                GetTextMetrics(g_hDC,&tm);

                //描画領域のサイズを調べる
                GetTextExtentPoint32(g_hDC,(LPCTSTR)pParam6,strlen((char*)pParam6),&size);

                //描画領域を透明色でクリアする
                WORD *pDIB = NULL;
                
                for(y = 0;y < size.cy;++y)
                {

                        pDIB = (WORD*)(g_pDIB + (PLANE_WIDTH << 1) * y);

                        for(x = 0;x < size.cx;++x)
                        {

                                //透明の黒で埋める
                                *pDIB = 0;
                                
                                //ポインタを1ピクセル進める
                                pDIB++;

                        }

                }       

                //1文字ずつ描画
                while((uChar = _mbsnextc(pMoji)) != 0)
                {

                        //1文字描画するのに必要なバッファのサイズを取得する
                        dwBuffSize = GetGlyphOutline(g_hDC,uChar,GGO_GRAY4_BITMAP,
                                                     &GlyphMetrics,0,NULL,&mat2);
                        
                        //必要なサイズが現在確保しているバッファより大きいか?
                        if(g_dwBuffSize < dwBuffSize)
                        {

                                //バッファを開放
                                delete[] g_pMoji;
                                g_pMoji = NULL;

                                //最大サイズを再設定
                                g_dwBuffSize = dwBuffSize;

                                //バッファを再作成
                                g_pMoji = new BYTE[g_dwBuffSize];

                        }
                        
                        //文字の描画情報を取得
                        //17段階(0〜16)のアンチエイリアス付きで取得
                        GetGlyphOutline(g_hDC,uChar,GGO_GRAY4_BITMAP,&GlyphMetrics,
                                        g_dwBuffSize,(LPVOID)g_pMoji,&mat2);

                        //文字の高さと幅の取得
                        mw = GlyphMetrics.gmBlackBoxX;
                        mh = GlyphMetrics.gmBlackBoxY;

                        //Alignを求める(32bit区切り)
                        int Align;

                        Align = (GlyphMetrics.gmBlackBoxX + 3) &0xFFFC;

                        //左上隅からの開始位置の取得
                        //GlyphMetrics.gmptGlyphOrigin = 左上からのオフセット
                        //tm.tmAscent = 文字のベースライン
                        offset_x = dstx +  GlyphMetrics.gmptGlyphOrigin.x;
                        offset_y = tm.tmAscent - GlyphMetrics.gmptGlyphOrigin.y;

                        //文字の幅と高さの分だけループして描画
                        for(y = 0;y < mh;++y)
                        {

                                for(x = 0;x < mw;++x)
                                {

                                        //α値の取得
                                        Alpha = (WORD)(*(g_pMoji + (y * Align) + x));

                                        //色があるとき
                                        if(Alpha != 0)
                                        {

                                                //値を4bit左にシフト
                                                //上位4ビットにα情報をもってくる
                                                Alpha = Alpha << 4;
                                                if(Alpha >= 0x0100) Alpha = 0x00F0;

                                                //α値を描画
                                                *(WORD*)(g_pDIB + ((PLANE_WIDTH << 1) 
                                                         * (offset_y + y)) + (offset_x + x)) = Alpha;

                                        }

                                }

                        }
                        
                        //次の描画位置へ移動
                        dstx += GlyphMetrics.gmCellIncX;        //次の文字への幅を加算する

                        //ポインタを次の文字へ進める
                        pMoji = _mbsinc(pMoji);

                }

                //テクスチャが作成されていなければ、作成する
                if(g_pMojiTex == NULL)
                        lpD3DDevice->CreateTexture(PLANE_WIDTH,PLANE_HEIGHT,1,0,
                                                   D3DFMT_A4R4G4B4,D3DPOOL_MANAGED,&g_pMojiTex);

                //テクスチャがあるか?
                if(g_pMojiTex != NULL)
                {

                        //描いた分だけテクスチャに転送  
                        D3DLOCKED_RECT d3dlocked_Rect;
                        
                        //テクスチャをロック
                        g_pMojiTex->LockRect(0,&d3dlocked_Rect,NULL,0);

                        //転送
                        BYTE *pTexBit = NULL;

                        for(y = 0;y < size.cy;++y)
                        {

                                //Y方向にポインタを移動
                                pTexBit = ((BYTE*)d3dlocked_Rect.pBits + d3dlocked_Rect.Pitch * y);
                                
                                //1ライン分転送
                                memcpy(pTexBit,g_pDIB + y * (PLANE_WIDTH << 1),size.cx << 1);
                                
                        }

                        //テクスチャをアンロック
                        g_pMojiTex->UnlockRect(0);

                        //描画用に頂点を作成
                        D3DTLVERTEX Vertex[4];

                        Vertex[0].x = fParam1;
                        Vertex[0].y = fParam2;
                        Vertex[0].z = 0.0f;
                        Vertex[0].rhw = 1.0f;
                        Vertex[0].tu0 = 0.0f;
                        Vertex[0].tv0 = 0.0f;
                        Vertex[0].color = dwParam3;

                        Vertex[1].x = fParam1;
                        Vertex[1].y = fParam2 + (float)size.cy;
                        Vertex[1].z = 0.0f;
                        Vertex[1].rhw = 1.0f;
                        Vertex[1].tu0 = 0.0f;
                        Vertex[1].tv0 = (float)size.cy / (float)PLANE_HEIGHT;
                        Vertex[1].color = dwParam3;

                        Vertex[2].x = fParam1 + (float)size.cx;
                        Vertex[2].y = fParam2;
                        Vertex[2].z = 0.0f;
                        Vertex[2].rhw = 1.0f;
                        Vertex[2].tu0 = (float)size.cx / (float)PLANE_WIDTH; 
                        Vertex[2].tv0 = 0.0f;
                        Vertex[2].color = 0xFF0000FF;//dwParam3;        //ちょっと遊びでグラデーション

                        Vertex[3].x = fParam1 + (float)size.cx;
                        Vertex[3].y = fParam2 + (float)size.cy;
                        Vertex[3].z = 0.0f;
                        Vertex[3].rhw = 1.0f;
                        Vertex[3].tu0 = (float)size.cx / (float)PLANE_WIDTH; 
                        Vertex[3].tv0 = (float)size.cy / (float)PLANE_HEIGHT;
                        Vertex[3].color = 0xFF0000FF;//dwParam3;        //ちょっと遊びでグラデーション

                        //現在のTextureStageStateを保存する
                        lpD3DDevice->GetTextureStageState(0,D3DTSS_MAGFILTER,&dwMAGFILTER);
                        lpD3DDevice->GetTextureStageState(0,D3DTSS_MINFILTER,&dwMINFILTER);
                        lpD3DDevice->GetTextureStageState(0,D3DTSS_COLORARG1,&dwCOLORARG1);

                        //フォントの縁がキレイになるようにする
                        lpD3DDevice->SetTextureStageState(0,D3DTSS_MAGFILTER,D3DTEXF_POINT);
                        lpD3DDevice->SetTextureStageState(0,D3DTSS_MINFILTER,D3DTEXF_POINT);
                        lpD3DDevice->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_DIFFUSE);

                        //テクスチャをセット
                        lpD3DDevice->SetTexture(0,g_pMojiTex);

                        //レンダリング
                        ret = lpD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,Vertex,sizeof(D3DTLVERTEX));

                        //テクスチャをはずす
                        lpD3DDevice->SetTexture(0,NULL);

                        //設定を元に戻す
                        lpD3DDevice->SetTextureStageState(0,D3DTSS_MAGFILTER,dwMAGFILTER);
                        lpD3DDevice->SetTextureStageState(0,D3DTSS_MINFILTER,dwMINFILTER);
                        lpD3DDevice->SetTextureStageState(0,D3DTSS_COLORARG1,dwCOLORARG1);
        
                        ret = S_OK;

                }

                //フォントの削除
                DeleteObject(SelectObject(g_hDC,hOldFont));

        }       
                
        return ret;

}
//---------------------------------------------------------------------------

 はい、どうでしょうか。これはDLLでの実装なので、ちょっと冗長な部分がありますが、そこらへんは自分のプログラムに都合のいい形に直してくださいね。

 また、この文字列描画は座標を2Dとして扱っているので、この文字列をグリグリ回転させたりはできません。
 そこらへんの対応はポリゴンの頂点データの形式を変えたり、座標変換用の行列や、カメラ行列、投影変換行列などが必要になるので、各自で勉強するようにしてください(^^;<無責任

 ちなみに、#includeのあとの<>は意図的に全角文字になっていますので、コピー&ペーストする場合は、直してくださいね。


 というわけで、ようやくDirectX8でキレイな文字列描画ができました。
 GetGlyphOutlineの使い方もわかったし、他の仕事にも生かせそうな感じなので、満足です(^^;
 このソースが誰かのお役に立てれば光栄です。


 それでは、今日はこの辺で、おやすみなさい。

0125
2002/02/14()
 むぁ〜 眠い 
 昨日MM音楽館の続きで、結構遅くまで起きてたので、眠いです(^^;

 今日も、昨日に引き続き、Direct3Dのお勉強です。今日は、サンプルを参考にしながら、立方体のオブジェクトにテクスチャを貼り付けて、グリグリまわしてました。
 昨日までは、3Dなんだけど表示が2Dのみだったので、なんかようやく3Dやってるって感じになりました(^^;

 その他、今度先日長野に納品したシステムが、新潟の長岡の方にも導入されることが決まったので、それ用のサーバマシンを組み立てました。
 バイトくんに必要な部品を大須に買いに行ってもらい、その後バイト君はさくっと帰ってしまったので、夕方からマシンを組み立てることにしました。

 このシステムのサーバに使うマシンのケースはとってもコンパクトなので、詰め込むのが大変でした(^^;
 で、5時間ほどかけて、組み立てとハードディスクのフォーマット&システムのインストールをしました。ああ、疲れた。

 それから、みんなでピザを頼んで、簡単な夕食にしました。

 集中して作業しているときは、眠たいのも忘れていましたが、インストール作業も済んで、ふぅ、と一息ついたら旧に眠くなったので、10分ほど仮眠してから帰りました。

 だいぶ外も寒くなったので、自転車で帰るのも大変です(^^;
 そして、部屋に帰った頃には眠気もピークに達したので、今日はなにもせずに、そのまま寝ることにします。

 そうそう、今日掲示板の方にまかべひろしさんが、DirectX8での文字列描画について、助言を下さりました。ありがとうございます。


 それでは、この辺でおやすみなさい。

0124
2002/02/13()
 今日はP/ECEやりました(^^; 
 ひあ、今日は仕事のDirectXで、80枚の画像を読み込んでテクスチャにし、連続的に描画してアニメーションさせたり、ウインドウモードとフルスクリーンモードを「Alt + Enter」で切り替えられるようにしたり、FPSを表示するようにしたりして、結構まともなアプリになってきました(^^;
 
 詳しい仕様がまだ決まっていないので、そう大きく進むことはできませんが、だんだんDirect3Dにも慣れてきていい感じです。

 そうそう、昨日も書いたけど、文字を描画するときに、Windows2000以降あるいは、Win98+Plus!以降で画面のプロパティの効果タブにある「スクリーン フォントの縁を滑らかにする」にチェックを入れておくと、TextOutでアンチエイリアス付きの文字が描画されますが、この情報はどうやらレジストリの「HKEY_CURRENT_USER\Control Panel\Desktop\FontSmoothing」に入っているようで、この値が"0"ならアンチエイリアスなしで、"1"または"2"ならアンチエイリアス付きです。

 が、このレジストリを変更しても、再起動しないと値がGDIに反映されません。なぜ!? 画面のプロパティではチェックを変えて「適用」ボタンですぐに反映されるのにぃ!!!!! くそう、MSめ。秘密のAPIかなんかを使ってやがるな、ちくしょう!

 というわけで、一応プログラムから設定の変更はできますが、要再起動というなんだそりゃ!? な結末を迎えてしまいました(^^; 誰か再起動しなくてもいい方法を御存知でしたら、どうか教えてくださいm(-_-)m

 で、今日も1日DirectXのお勉強に励んで、部屋に帰りました。


 部屋に帰ってからは、またそろそろP/ECEをいぢらないとねぇ…… ということで、MM音楽館の続きをしました。一応次の公開Ver.は0.87ということで、はらやんさんに倣って「壁紙」機能をつけました。
 これは、フラッシュメモリ内に"mmmhwall.pgd"という128*88の画像ファイルがあった場合に、それを壁紙として表示するというもの。

 また、MMLの#Title2内に";"を書くと改行に変換されるmuccの仕様に対応して、改行コードをスペースに変換して、2行目以降もちゃんと表示できるように修正しました。


 とりあえず、修正したかったのは、この2つで、これでVer.0.87は完成なのですが、今日はもう遅いので、公開は明日にします〜。うう、寒い。眠い。

 これ以降は、お楽しみも〜ど付きのVer.0.9xになる予定です。P/ECE上でのエディタも出てきたことだし、そろそろプレイリストにも対応した方がいいかな。または、演奏マークをつけて、マークのあるものだけ演奏するとかいう風にした方がいいのかなぁ。うーん。

 あと、なんか最近演奏するテンポが速くなった気がするが、気のせいだろうか。テンポなんていぢってないのでかわるはずないのですが、もしかしてmuslib変わっちゃってる? やっぱ気のせいかなぁ。

 というわけで、今日はこの辺でお別れです。
 それでは、おやすみなさい。 

0123
2002/02/12()
 うーん、眠い 
 えー、今日は先週から引き続きDirectXを使う仕事をしてました。

 今日は、先週使った文字列表示の方法とは別の方法で、文字列を描画することに挑戦しました。

 先週の方法はD3DXFontを使う方法で、簡単なのですが、遅くて実用的ではないので、今日はDIBセクションと文字表示用のテクスチャを用意して、DIBをメモリDCに関連付けて、文字列をAPIで描画してから、テクスチャに転送するという方法を試しました。

 が、思ったよりも上手くいかず、結構悩んでしまいました(^^;

 現在テストに使用しているのはIntelの815チップセットで、グラフィック機能はちょっと弱いのですが、今作っているアプリが将来ノートパソコンで動かす予定なので、ちょうどいいくらいの性能です。

 で、普通に32ビットのテクスチャを作成してアルファ値付きで文字列を描画しようと試みましたが、815には32bitモードはなく、さらに、WindowモードではDirect3Dの方が、24bitに対応していないので、結局16bitモードでやることになりました。

 16bitモードでは、A1R5G5B5やA4R4G4B4などのピクセルフォーマットが使用可能なのですが、なーんかうまく色がでてくれなかったり、勝手にアンチエイリアスがかかったり。結構てこずりました(^^;

 で、最終的に、アンチエイリアスはRenderStateのミップマップフィルタや拡大フィルタでバイリニア補完しないようにしたり、画面のプロパティの「効果」で「スクリーンフォントの縁を滑らかにする」のチェックをはずすことで、かからなくすることができることがわかりましたが、画面のプロパティの内容をプログラムから操作する方法がわからないので、ここら辺については、保留にしました。

 というわけで、今日は文字を別の方法で描画するところまでで終わりました。
 ほんとは社長と打ち合わせとかしたかったのですが、外に出て行ってしまったのでまた今度に持ち越しです。
 ちなみに、明日も朝から居ないらしいので、明日は他の人と別の打ち合わせでもしようかな。

 そういえば、今日は昨日の夜から降り続いた雪で、朝は大変でした。でも、晴れだったので、帰る頃にはすっかり雪がなくなっていました。


 ふぅ。なんか、調子がちょっと崩れたみたいで、眠いです。
 ちょっと疲れ気味みたいな感じなので、しばらくP/ECEの開発はできないかなぁ。MM音楽館の続きや、いろさんが提案してくれたOLYMP/ECEの企画にも参加したいんだけど、うーむ。眠い。

 というわけで、今日は早めに寝ることにします。
 それでは、おやすみなさい。 

0122
2002/02/11()
 今日はお買い物 
 今日は、彼女と2人でJRタワーズにある東急ハンズや名駅地下街、その他いろいろでお買い物を楽しみました。

 お菓子を買ったり、のぽぽんを買ったり、本を買ったり。楽しかったです。

 お昼は久しぶりに「チャオ」でシシリアンを食べました。
 夕飯は私の部屋の結構近くにある「風来坊」で手羽先やら串盛やら、こぶ茶漬けやら、たらふく食べました(^^;

 めいっぱい休日を楽しんだので、部屋に帰ってからは、すぐに寝ちゃいました。

 というわけで、短いですが、今日はおしまい。
 それでは、おやすみなさい。