mieki256's diary



2023/05/29(月) [n年前の日記]

#1 [cg_tools] MiDaSの動かし方が分かったのでメモ

1枚の静止画像から奥行きを推測してデプスマップ(深度マップ、z map)を作れる MiDaS というアルゴリズム? AI? が気になった。

_MiDaS | PyTorch
_GitHub - isl-org/MiDaS

ローカル環境で動かせるようにするための手順が分かったので一応メモ。

環境は以下。
AI関係のプログラムだから動かすためにはGPUが必要なのかなと思っていたけど、CPUだけでも処理できるっぽい。その分処理時間は増えてしまうのだろうけど、数秒で結果が得られてるようなので、その程度の処理時間で済むならCPUで処理しても問題無いかなと…。まあ、リアルタイムに処理したいとか、膨大な枚数を処理したい場合は、GPUが必要になるのかも。

導入手順をざっくりと列挙すると、以下のような感じ。
  1. github から MiDaS関連のファイル群を git clone で入手。
  2. Pythonの仮想環境を作成。
  3. MiDaSの動作に必要なPythonモジュールをインストール。
  4. 学習モデルデータを入手して weights フォルダに入れる。
  5. run.py を実行して動作確認。

githubからクローン :

以下のページから、git を使ってプロジェクトファイル?一式をクローンする。

_GitHub - isl-org/MiDaS

今回は、D:\aiwork\midas\ というフォルダを作成して、その中で作業してみた。

git clone https://github.com/isl-org/MiDaS.git

MiDaS というフォルダが作られて、ファイル一式がダウンロードされた。

Pythonの仮想環境を作成 :

MiDaS を動かすためには、Pyhonの色々なモジュールが必要になる。普段利用してるPython環境にそれらのモジュールをインストールしてしまうと、各モジュールのバージョン管理が面倒になるので、仮想環境を作成して、その中で作業することにしたい。

MiDaSフォルダの中に入って、venv を使って仮想環境を作成。
cd MiDaS
python -m venv venv
  • -m venv : venv というモジュールを使え、と指示してる。
  • 最後の venv はフォルダ名(ディレクトリ名)。venv というフォルダの中に仮想環境を作れ、と指示してる。フォルダが無かったら自動でフォルダ作成してくれる。

venv というフォルダが作成されて、その中にPythonの環境が入った。

仮想環境のPythonに切り替える。
venv\Scripts\activate

インストールされているモジュールの一覧を表示する。
pip list
(venv) D:\aiwork\midas\MiDaS> pip list
Package    Version
---------- -------
pip        22.2.1
setuptools 63.2.0

[notice] A new release of pip available: 22.2.1 -> 23.1.2
[notice] To update, run: python.exe -m pip install --upgrade pip

pip と setuptools、2つのモジュールしか入ってない奇麗な状態。

ところで、「pipの新しいバージョンがあるよ」「python.exe -m pip install --upgrade pip を実行して更新できるよ」と表示されてるので、一応更新しておく。
python.exe -m pip install --upgrade pip

必要なモジュールをインストール :

githubから入手したファイル群の中に environment.yaml というファイルがある。この中に、使っているモジュールのバージョンが記録されていた。引用してみる。

environment.yaml
name: midas-py310
channels:
  - pytorch
  - defaults
dependencies:
  - nvidia::cudatoolkit=11.7
  - python=3.10.8
  - pytorch::pytorch=1.13.0
  - torchvision=0.14.0
  - pip=22.3.1
  - numpy=1.23.4
  - pip:
    - opencv-python==4.6.0.66
    - imutils==0.5.4
    - timm==0.6.12
    - einops==0.6.0

試したところ、これらのバージョンを使わないと、よく分からないエラーがバンバン出てしまったので…。バージョンを指定しつつモジュールをインストールしていく。

ちなみに、MiDaS を動かすにあたって重要なのは timm というモジュールっぽい。このモジュールをインストールすれば、MiDaS を動かすために必要なモジュールのほとんどがインストールできてしまう模様。ただ、依存してるモジュールのバージョンまで合わせてくれるわけではないらしい…。最新版のモジュールが入ってしまう…。

pip を使ってインストールしていく。
pip install timm==0.6.12
pip install torchvision==0.14.0
pip install torch==1.13.0
pip install numpy==1.23.4
pip install einops==0.6.0
pip install imutils==0.5.4
pip install opencv-python==4.6.0.66

他に、opencv-contrib-python も必要っぽい。これを入れないとエラーが出てしまった。また、サンプルスクリプトを眺めると、matplotlib も必要になりそう。インストールしておく。
pip install opencv-contrib-python==4.6.0.66
pip install matplotlib

インストールされたモジュール一覧を確認。environment.yaml に記述されたバージョンと一致してるか確認しておく。
> pip list
Package               Version
--------------------- --------
certifi               2023.5.7
charset-normalizer    3.1.0
colorama              0.4.6
contourpy             1.0.7
cycler                0.11.0
einops                0.6.0
filelock              3.12.0
fonttools             4.39.4
fsspec                2023.5.0
huggingface-hub       0.14.1
idna                  3.4
imutils               0.5.4
Jinja2                3.1.2
kiwisolver            1.4.4
MarkupSafe            2.1.2
matplotlib            3.7.1
mpmath                1.3.0
networkx              3.1
numpy                 1.23.4
opencv-contrib-python 4.6.0.66
opencv-python         4.6.0.66
packaging             23.1
Pillow                9.5.0
pip                   23.1.2
pyparsing             3.0.9
python-dateutil       2.8.2
PyYAML                6.0
requests              2.31.0
setuptools            63.2.0
six                   1.16.0
sympy                 1.12
timm                  0.6.12
torch                 1.13.0
torchvision           0.14.0
tqdm                  4.65.0
typing_extensions     4.6.2
urllib3               2.0.2

学習モデルデータを入手 :

MiDaS を動かすためには学習モデルデータも必要。この学習モデルデータは、精度が高いけど容量が大きいもの、精度は低いけど容量が少なくて済むもの ―― 色々な種類がある。

_GitHub - isl-org/MiDaS
_Release MiDaS 3.1 - isl-org/MiDaS - GitHub
_Release MiDaS v3 (DPT) - isl-org/MiDaS - GitHub

上記ページから、dpt_beit_large_512, dpt_hybrid_384 等々の学習モデルデータを入手する。ファイルの拡張子は .pt。

今回は以下のファイルを入手してみた。
dpt_beit_large_512.pt (1.5GB)
dpt_hybrid_384.pt (470MB)
dpt_large_384.pt (1.3GB)
dpt_levit_224.pt (196MB)
dpt_swin2_large_384.pt (840MB)
dpt_swin2_tiny_256.pt (165MB)

各 .pt を入手できたら、weights というフォルダの中にコピーする。

余談。各ファイル名についている 512, 384, 256, 224 という数字は、512x512, 384x384, 256x256, 224x224 で学習したよ、という意味らしい。

余談その2。画像生成AI Stable Diffusion web UI の ControlNet で使っているのは、dpt_hybrid_384.pt だった。

余談その3。学習モデルデータも含めて、全体のファイル群は、5.55GBになった。

テスト画像を入手 :

テストする画像を入手して、inputフォルダの中に入れておく。おそらく、pngの他にjpgもイケそう。公式サイトのサンプルでは犬の写真画像を使ってたので、それに倣ってみる。以下から入手。

_hub/dog.jpg at master - pytorch/hub - GitHub

dog.jpg をダウンロードして、inputフォルダに入れた。

サンプルスクリプトを実行 :

githubから入手したファイル群の中に、run.py というPythonスクリプトがある。このスクリプトを実行することで MiDaS の動作確認ができるらしい。

python run.py --model_type dpt_hybrid_384 --input_path input --output_path output
  • --model_type dpt_hybrid_384 : 学習モデルデータとして dpt_hybrid_384 を指定。別の学習モデルデータを使いたい時は変更する。
  • --input_path input : 画像が入ってるフォルダを指定。inputフォルダを指定してる。
  • --output_path output : 結果画像の保存先フォルダを指定。outputフォルダを指定してる。

実行すると、こうなった。
(venv) D:\aiwork\midas\MiDaS> python run.py --model_type dpt_hybrid_384 --input_path input --output_path output
Initialize
Device: cpu
Model loaded, number of parameters = 123M
Start processing
  Processing input\dog.jpg (1/1)
    Input resized to 480x384 before entering the encoder
Finished
「Device: cpu」と表示されてるので、GPUではなくCPUで処理してるのだろう…。また、「入力された画像を 480x384 にリサイズしてから処理してるよ」とも表示されてる。

outputフォルダ内に、以下の2つのファイルが生成された。
dog-dpt_hybrid_384.pfm
dog-dpt_hybrid_384.png

.png はPNG画像だろうけど、.pfm とは何ぞや。

_画像フォーマット

PFM = Portable Float Map、らしい。Float…? それはつまり、各ドットの情報を浮動小数点数で持ってるということだろうか。1チャンネル8bitしか情報を持ってないPNGと比べたら、めっちゃ豊かな情報を持ってそう。

さておき。.png はフツーに表示できる。

dog-dpt_hybrid_384.png

たしかにデプスマップを得られた。これで MiDaS をローカル環境で動かすことができた…。


ところで、run.py に渡す --model_type で学習モデルデータを指定できるのだけど、公式ページのドキュメントでは以下が指定できると書いてあった。もちろん、学習モデルデータ(.pt)を入手して weightsフォルダに入れてあればの話。
dpt_beit_large_512
dpt_beit_large_384
dpt_beit_base_384
dpt_swin2_large_384
dpt_swin2_base_384
dpt_swin2_tiny_256
dpt_swin_large_384
dpt_next_vit_large_384
dpt_levit_224
dpt_large_384
dpt_hybrid_384
midas_v21_384
midas_v21_small_256
openvino_midas_v21_small_256

謎の警告が少し気になる :

学習モデルデータとして dpt_beit_large_512 を指定すると、何故かエラーが、というか警告が出る…。一応、結果画像は得られるのだけど…。
(venv) D:\aiwork\midas\MiDaS> python run.py --model_type dpt_beit_large_512 --input_path input --output_path output
Initialize
Device: cpu
D:\aiwork\midas\MiDaS\venv\lib\site-packages\torch\functional.py:504: UserWarning: torch.meshgrid: in an upcoming release, it will be required to pass the indexing argument. (Triggered internally at ..\aten\src\ATen\native\TensorShape.cpp:3191.)
  return _VF.meshgrid(tensors, **kwargs)  # type: ignore[attr-defined]
Model loaded, number of parameters = 345M
Start processing
  Processing input\dog.jpg (1/1)
    Input resized to 640x512 before entering the encoder
Finished

「今後のリリースではインデックス引数が必要になりますよ」と言ってるようだけど…。コレ、どうすればいいんだろう…?

MiDaS 3.0 の学習モデルデータを使うとこの警告は出てこないけど、MiDaS 3.1 の学習モデルデータを使うと出てくるようではあるなと…。

グレイスケール画像で出力したい :

現状の run.py は、人間が目で見て分かりやすくするために、デプスマップを色付きの画像で出力しているけれど。他の何かに渡して処理したい場合、グレースケール画像で出力してくれたほうが嬉しいわけで…。

そんな時は、--grayscale をつければいいらしい。
python run.py --model_type dpt_large_384 --input_path input --output_path output --grayscale

dog-dpt_large_384.png

たしかにグレースケールになった。

その他のオプション :

run.py に --help をつければ、ヘルプが表示される。
> python run.py --help
usage: run.py [-h] [-i INPUT_PATH] [-o OUTPUT_PATH] [-m MODEL_WEIGHTS] [-t MODEL_TYPE] [-s]
              [--optimize] [--height HEIGHT] [--square] [--grayscale]

options:
  -h, --help            show this help message and exit
  -i INPUT_PATH, --input_path INPUT_PATH
                        Folder with input images (if no input path is specified, images are tried
                        to be grabbed from camera)
  -o OUTPUT_PATH, --output_path OUTPUT_PATH
                        Folder for output images
  -m MODEL_WEIGHTS, --model_weights MODEL_WEIGHTS
                        Path to the trained weights of model
  -t MODEL_TYPE, --model_type MODEL_TYPE
                        Model type: dpt_beit_large_512, dpt_beit_large_384, dpt_beit_base_384,
                        dpt_swin2_large_384, dpt_swin2_base_384, dpt_swin2_tiny_256,
                        dpt_swin_large_384, dpt_next_vit_large_384, dpt_levit_224, dpt_large_384,
                        dpt_hybrid_384, midas_v21_384, midas_v21_small_256 or
                        openvino_midas_v21_small_256
  -s, --side            Output images contain RGB and depth images side by side
  --optimize            Use half-float optimization
  --height HEIGHT       Preferred height of images feed into the encoder during inference. Note
                        that the preferred height may differ from the actual height, because an
                        alignment to multiples of 32 takes place. Many models support only the
                        height chosen during training, which is used automatically if this
                        parameter is not set.
  --square              Option to resize images to a square resolution by changing their widths
                        when images are fed into the encoder during inference. If this parameter
                        is not set, the aspect ratio of images is tried to be preserved if
                        supported by the model.
  --grayscale           Use a grayscale colormap instead of the inferno one. Although the inferno
                        colormap, which is used by default, is better for visibility, it does not
                        allow storing 16-bit depth values in PNGs but only 8-bit ones due to the
                        precision limitation of this colormap.

-i input, -o output, -t dpt_hybrid_384 といった記述も指定できるっぽいな…。

run.py を眺めてみたけど、--model_type を指定しない場合、dpt_beit_large_512 がデフォルトで指定される模様。

Webカメラからの入力 :

試しに python run.py だけで動かしたら、ウインドウが表示されて何かを表示し続けてるようではあった。

DOS窓には「No input path specified. Grabbing images from camera.」と表示されてたので、Webカメラの入力を処理しようとしてたっぽい。でも、自分のPC、Webカメラついてないんですけど…。ウインドウを閉じて強制終了した…。

せっかくだから、Webカメラからの入力も試してみた。USB接続Webカメラ BUFFALO BSWHD01 を部屋から発掘して接続。python run.py を実行。こんな感じになった。

midas_webcamera_ss01.png

たしかに、Webカメラからの入力に対して処理できてるようだなと…。

DOS窓上では「FPS: 0.47」と表示されていた。1フレームを数秒かけて処理して返してる状態なのだな…。もしかするとGPUで処理できたらもっと速く結果が得られるのだろうか。

ウインドウのタイトルに「ESCキーで抜けられるよ」と書いてあることに気づいた。ESCキーを数秒間ポンポンポンと連打していたら、ウインドウが閉じてくれた。

参考ページ :

余談 :

MiDaS を触っていてふと思ったことをなんとなくメモ。思考メモ。

奥行き情報を取得しようとする場合、本来であれば2台のカメラで撮影して視差情報を利用して、とかやらないといかんのだろうと思うのだけど。1枚の静止画像から「たぶんこんな感じじゃねえかなあ」とAIが奥行き情報を作ってくれるなんて、スゴイことになってるなと…。仕組みを実現してしまった方々、凄過ぎる…。

もっとも、人間だって写真やTV映像を見て、「この人は手前に立っている」「この建物は奥にある」などと無意識に推測しながら認識してるわけで。

視差情報も無いのにどうしてそんなことができるかと言えば、それはやはり学習の賜物。自分の身の回りの風景を二つの目で捉えて距離感を測る訓練を延々してきたから、単眼で捉えた視覚情報に対しても前後関係を推測することができているのだろうなと。そう考えると、人間ってなかなかスゴイことしてるなと…。

そして、「人間が学習で能力を獲得しているのだから、コンピュータだって学習すれば似たようなことができらあ!」と ―― ある種乱暴だけど楽観的な思考が根底にあるから、こういった技術がここまで発達してきたような、そんな気もする。と言っても、何をどう学習させるか、そこが閃かなかったらどうにもならないのだろうけど。

余談その2 :

妄想メモ。

1枚の静止画像から奥行き情報を推測できるなら…。別々の方向から撮影した数枚の画像があれば、色んな方向から見た深度情報を得られるよなと。その複数の深度情報を擦り合わせていったら、より正確な3D形状を得られたりしないだろうか。などと妄想。

でも、複数の方向から撮影できてる時点でそこには視差情報が含まれてるから、ソレを使って形状を構成するほうが妥当な気もしてきた。

まあ、そういう研究は既に誰かがやってるだろう…。というか、スマホで数枚撮影してそこから形状を作ってしまうサービスを結構前にどこかで見かけた気もするし…。

MiDaSのような技術は、「一枚の静止画しかないですけどコレ使ってとにかくどうにかしてください」というある種縛りプレイを強要される状況でこそ使える技術、だよな…。「もし必要なら色んな方向から撮影できますよ」と言ってもらえる恵まれた状況なら別の技術を使ったほうが…。

2022/05/29() [n年前の日記]

#1 [xscreensaver] xscreensaver用のスクリーンセーバを作りたい。その2

_昨日 に続いて、xscreensaver用のスクリーンセーバを自分で作れないか実験中。

_README.hacking に、新しいスクリーンセーバを作る際に意識することが書かれてあるので、眺めながら作業。

環境は Ubuntu Linxu 20.04 LTS。

とりあえず、hacks/ディレクトリ内で、deluxe.c、deluxe.man、config/deluxe.xml をコピーして、helloxsaver.c、helloxsaver.man、config/helloxsaver.xml の3ファイルを作ったけれど。まだ中身が deluxe.c のままだし、deluxe.c は色々と複雑な処理をしているように見えるので、ガシガシ削って、ダブルバッファ描画処理の骨の部分だけを残して、更に、画面の中でボール(円)が跳ね回るだけの処理を書いてみた。

実行結果は以下のような感じ。どこでもよく見かけるアレ。

ソースファイル。 :

ソースは以下。長い。長いけど、「ball」で検索すれば、肝心の処理部分だけがなんとなく見えてくるかなと。それ以外はダブルバッファ描画関係の処理なので、極端な話、気にしなくいい。ダブルバッファ処理をしたいなら、まるっとコピペして、後は独自の処理だけを書き加えればいいのではなかろうかと。

_helloxsaver.c
/* xscreensaver, Copyright (c) 2022 YOURNAME <YOURNAME@example.com>
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation.  No representations are made about the suitability of this
 * software for any purpose.  It is provided "as is" without express or
 * implied warranty.
 */

#include <math.h>
#include "screenhack.h"
#include "alpha.h"

#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
#include "xdbe.h"
#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */

#define PI 3.141592

/* degree to radian */
static double deg2rad(double angle)
{
  return (angle * PI / 180.0);
}

/* screensaver state */
struct state
{
  Display *display;
  Window window;

  int nplanes;
  unsigned long base_pixel;
  unsigned long *plane_masks;

  Bool monochrome;
  Bool use_dbuf;

  int delay;
  int speed;

  double x, y;   /* ball position */
  double dx, dy; /* ball direction */
  int w, h;      /* ball width, height */
  GC gc;         /* graphics context */

  XWindowAttributes xgwa;

  XColor color;
  GC erase_gc;

  /* double-buffer to reduce flicker */
  Pixmap backbuf;
  Pixmap ba;
  Pixmap bb;

#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
  Bool dbeclear_p;
  XdbeBackBuffer backb;
#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
};

/* initialize ball position */
static void
init_ball_pos(struct state *st)
{
  int sw, sh;
  sw = st->xgwa.width;  /* window width */
  sh = st->xgwa.height; /* window height */

  /* set width and height */
  st->w = st->h = ((sw > sh) ? sh : sw) / 16;

  /* set position */
  st->x = (random() % (sw / 2)) + (sw / 4);
  st->y = (random() % (sh / 2)) + (sh / 4);

  /* set direction */
  {
    double rad;
    rad = deg2rad(random() % 360);
    st->dx = st->speed * cos(rad);
    st->dy = st->speed * sin(rad);
  }
}

/*
 * init screensaver.
 * Return an object holding your global state.
 */
static void *
helloxsaver_init(Display *display, Window window)
{
  struct state *st = (struct state *)calloc(1, sizeof(*st));

  st->display = display;
  st->window = window;

  /* get parameter */
  st->delay = get_integer_resource(st->display, "delay", "Integer");
  st->speed = get_integer_resource(st->display, "speed", "Speed");
  st->use_dbuf = get_boolean_resource(st->display, "doubleBuffer", "Boolean");
  st->monochrome = get_boolean_resource(st->display, "mono", "Boolean");

#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
  st->dbeclear_p = get_boolean_resource(st->display, "useDBEClear", "Boolean");
#endif

#ifdef HAVE_JWXYZ /* Don't second-guess Quartz's double-buffering */
  st->use_dbuf = False;
#endif

  /* get window attributes */
  XGetWindowAttributes(st->display, st->window, &st->xgwa);

  /* define colors */
  st->color.pixel = get_pixel_resource(st->display, st->xgwa.colormap,
                                       "foreground", "Foreground");

  if (st->use_dbuf)
  {
    /* init double buffer */

#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
    if (st->dbeclear_p)
      st->backbuf = xdbe_get_backbuffer(st->display, st->window, XdbeBackground);
    else
      st->backbuf = xdbe_get_backbuffer(st->display, st->window, XdbeUndefined);
    st->backb = st->backbuf;
#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */

    if (!st->backbuf)
    {
      /* create buffer A, B */
      st->ba = XCreatePixmap(st->display, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth);
      st->bb = XCreatePixmap(st->display, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth);
      st->backbuf = st->ba;
    }
  }
  else
  {
    st->backbuf = st->window;
  }

  /* init graphics context. use erase. */
  {
    XGCValues gcv;
    gcv.foreground = get_pixel_resource(st->display, st->xgwa.colormap,
                                        "background", "Background");
    st->erase_gc = XCreateGC(st->display, st->backbuf, GCForeground, &gcv);
  }

  /* clear buffer A, B */
  if (st->ba)
    XFillRectangle(st->display, st->ba, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height);

  if (st->bb)
    XFillRectangle(st->display, st->bb, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height);

  /* initialize ball position */
  init_ball_pos(st);

  /* init graphics context */
  {
    XGCValues gcv;
    unsigned long flags;

    flags = GCForeground;
    gcv.foreground = st->color.pixel;
    gcv.line_width = 2;
    gcv.cap_style = CapProjecting;
    gcv.join_style = JoinMiter;
    flags |= (GCLineWidth | GCCapStyle | GCJoinStyle);
    st->gc = XCreateGC(st->display, window, flags, &gcv);
  }

  return st;
}

/* Draw a single frame */
static unsigned long
helloxsaver_draw(Display *display, Window window, void *closure)
{
  struct state *st = (struct state *)closure;

  /* clear double buffer  */
#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
  if (!st->dbeclear_p || !st->backb)
    XFillRectangle(st->display, st->backbuf, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height);
#else
  XFillRectangle(st->display, st->backbuf, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height);
#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */

  /* ball move and draw */
  {
    /* draw circle */
    XFillArc(st->display, st->backbuf, st->gc, st->x, st->y, st->w, st->h, 0, 360 * 64);

    /* move */
    st->x += st->dx;
    st->y += st->dy;

    /* change directon */
    if (st->x <= 0 || (st->x + st->w) >= st->xgwa.width)
      st->dx *= -1;
    if (st->y <= 0 || (st->y + st->h) >= st->xgwa.height)
      st->dy *= -1;
  }

  /* draw double buffer */
#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
  if (st->backb)
  {
    XdbeSwapInfo info[1];
    info[0].swap_window = st->window;
    info[0].swap_action = (st->dbeclear_p ? XdbeBackground : XdbeUndefined);
    XdbeSwapBuffers(st->display, info, 1);
  }
  else
#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
    if (st->use_dbuf)
    {
      XCopyArea(st->display, st->backbuf, st->window, st->erase_gc, 0, 0,
                st->xgwa.width, st->xgwa.height, 0, 0);
      st->backbuf = (st->backbuf == st->ba ? st->bb : st->ba);
    }

  return st->delay;
}

/* Called when the window is resized. */
static void
helloxsaver_reshape(Display *display, Window window, void *closure,
                     unsigned int w, unsigned int h)
{
  struct state *st = (struct state *)closure;
  if (!st->use_dbuf)
  { /* #### more complicated if we have a back buffer... */
    XGetWindowAttributes(st->display, st->window, &st->xgwa);
    XClearWindow(display, window);
    
    init_ball_pos(st);
  }
}

/* Called when a keyboard or mouse event happens. */
static Bool
helloxsaver_event(Display *display, Window window, void *closure, XEvent *event)
{
  return False;
}

/* Free everything you've allocated. */
static void
helloxsaver_free(Display *display, Window window, void *closure)
{
  struct state *st = (struct state *)closure;

  XFreeGC(display, st->erase_gc);

  if (st->ba)
    XFreePixmap(display, st->ba);

  if (st->bb)
    XFreePixmap(display, st->bb);

  if (st->plane_masks)
    free(st->plane_masks);

  XFreeGC(display, st->gc);
  free(st);
}

/* Default values for the resources you use. */
static const char *helloxsaver_defaults[] = {
    ".background:		black",
    ".foreground:		white",
    "*delay:		10000",
    "*speed:		15",
    "*doubleBuffer:	True",
#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
    "*useDBE:		True",
    "*useDBEClear:	True",
#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
#ifdef HAVE_MOBILE
    "*ignoreRotation:     True",
#endif
    0};

/* The command-line options you accept. */
static XrmOptionDescRec helloxsaver_options[] = {
    {"-delay", ".delay", XrmoptionSepArg, 0},
    {"-speed", ".speed", XrmoptionSepArg, 0},
    {"-db", ".doubleBuffer", XrmoptionNoArg, "True"},
    {"-no-db", ".doubleBuffer", XrmoptionNoArg, "False"},
    {0, 0, 0, 0}};

/*
 * The last line of the file should be
 * XSCREENSAVER_MODULE ("YourSaverName", yoursavername)
 */

XSCREENSAVER_MODULE("Helloxsaver", helloxsaver)


マニュアルファイル(.man)と、設定画面定義ファイル(.xml) は以下。

_helloxsaver.man
_helloxsaver.xml

  • *.c, *.man は、hacks/ 以下にコピー。
  • *.xml は、hacks/config/ 以下にコピー。

make でビルド。sudo make install でインストールして、xscreensaverの設定画面を出して動作確認。
make
sudo make install
xscreensaver-settings &

少し解説。 :

最初のあたりで state という構造体を定義している。これは、このスクリーンセーバが動いてる最中、ずっと保持されるべきワークエリアの定義。動作に必要な変数は、全てこの state の中に入れておくことになる。

helloxsaver_init() は初期化処理を担当する。state 分のメモリ領域を確保・初期化して、関数を抜けるときに return st; で、呼び出し元に state のポインタを返している。xscreensaver本体は、この返されたメモリ領域を、スクリーンセーバが動いてる最中、ずっと保持しているのだろう。たぶん。

helloxsaver_draw() は、1フレーム分の描画を担当する関数。引数として state のポインタが渡されているので、そのワークエリアを使って処理をする。

helloxsaver_reshape() は、ウインドウサイズが変更された時に呼ばれるらしい。ここでは、ウインドウの情報(横幅、縦幅等々)を取得し直して、画面クリアと、ボールの位置を初期化してる。

helloxsaver_event() は、キーボード等が押された時に呼ばれるらしいが、return False; だけを書いておけばいい。

helloxsaver_free() は、ワークエリアの開放処理を書く。

グローバル変数、helloxsaver_defaults は、パラメータのデフォルト値を列挙。helloxsaver_options には、コマンドラインオプションを列挙する。

そして、一番最後の行に、以下を書く。

XSCREENSAVER_MODULE("Helloxsaver", helloxsaver)

もし、hoge という名前のスクリーンセーバを書くなら、最後の行は以下になるはず。
XSCREENSAVER_MODULE("Hoge", hoge)

ちなみに、xscreensaver用のスクリーンセーバとして公開する時は、*.c、*.man、*.xml 内の日付(年)や YOURNAME の部分を自分のソレに書き換えるようにと、 _README.hacking には書かれていた。

もう一つ書いてみた。 :

helloxsaver2 という名前でもう一つ書いてみた。実行結果は以下。ボールが複数跳ね回る例のアレ。



ソースファイル等は以下。

_helloxsaver2.c
_helloxsaver2.man
_helloxsaver2.xml

ファイルが増えたので、以下の2つを修正する必要がある。
  • hacks/Makefile.in
  • driver/XScreenSaver.ad.in

_Makefile.in.patch
_XScreenSaver.ad.in.patch

各所に、helloxsaver2.* を追加する。

修正できたら、以下を実行して、Makefile や XScreenSaver.ad を自動生成し直す。
./configure --prefix=/usr --libexecdir=/usr/lib

make してビルドして、インストールして、設定画面を出して動作確認。
make
sudo make install
xscreensaver-settings &

課題。 :

X11の描画機能を使って、線のみで円を描いたり、塗り潰しで円を描いたりすることができると分かった。円が描けるなら、おそらく四角や線や点も描けそうな気がする。

ただ、できれば画像を描画したい。最低限、画像の描画さえできれば、大昔の2Dゲームっぽい画面を作れるだろうから、かなり表現の幅が広がるはず。

しかし、画像を描画する方法が分からない…。

C言語のソースに、xpm画像をインポートしてやれば ―― #include "images/hoge.xpm" とでも書いてやれば、実行バイナリに画像データを含めることができるのではないかと思ったけれど、試してみたら xpm画像は扱えないと怒られた。xscreensaver は、xpm関連ライブラリをリンクしているわけではないのかもしれない。

画像を読み込んで描画してそうなスクリーンセーバはどれかなと探してみたけど、これがなかなか…。noseguy.c あたりがソレっぽいかなと眺めてみたけど、何が何だか。

画像の扱い方について。 :

画像の扱い方について調べてたのだけど、少し分かってきた。

hacks/images/ の中に、大量の画像が入っている。これらが、xscreensaver が利用する画像なのだろう。

また、hacks/images/Makefile による指定で、.png を .h に変換してることも分かった。ワイルドカード(*.png)を使って対象ファイル群が指定されているので、とにかく hacks/images/ の中にpng画像を入れておけば、それだけで変換処理対象として扱ってくれるらしい。

hacks/images/gen/ の中に、大量の *.h が入ってるけれど、これが、hacks/images/*.png をC言語のソース形式に変換したもの。中では unsigned char で、png画像のバイナリが列挙されている。

static const unsigned char nose_f1_png[] =
 "\211PNG\015\012\032...\000IEND\256B`\202";

  • hacks/images/gen/*.h は、make 時に自動生成されるので、ソースファイル群を解凍した段階では存在していない。
  • png画像から *.h への変換は、utils/bin2c というシェルスクリプトで行われている。実際には、bin2c の中で、Perl のワンライナーを指定して変換処理をしている。


さておき。これら、images/gen/*.h を、スクリーンセーバの *.c の中で include すれば、スクリーンセーバの実行バイナリの中に、png画像データもまるっと含まれて、画像データにアクセスできるようになるのだろう。例えば、下記なら、nose-f[1-4].png が実行バイナリに含まれることになる。

#include "images/gen/nose-f1_png.h"
#include "images/gen/nose-f2_png.h"
#include "images/gen/nose-f3_png.h"
#include "images/gen/nose-f4_png.h"


画像の読み込みをする場合は、ximage-loader.h を include する模様。

#include "screenhack.h"
#include "ximage-loader.h"

ximage-loader.h の中を覗いたら、一番最初の行に、「ximage-loader.h --- converts XPM data to Pixmaps.」と書いてあった。もしかして、xpm画像も使える…? また、その下で、image_data_to_pixmap()、image_data_to_ximage() 等々、それらしい名前の関数が宣言されていた。これらの関数を使えば、png画像のバイナリを Pixmap や XImage に変換できそう。たぶん。

2021/05/29() [n年前の日記]

#1 [movie] 「ゴジラ キング・オブ・モンスターズ」を視聴

TV放送されてたので視聴。初見。ハリウッド版のゴジラ映画で、ゴジラ以外の怪獣もたくさん登場するらしい。

CG、凄いなあ…。どの怪獣の登場カットも、スケール感がとんでもない…。こういう映像を見れるだけでも満足というか。

ただ、正直なところ、途中で挿入される人間ドラマパート・家族愛パートがちょっと鬱陶しかった。でも、こういう要素を入れておかないと、ハリウッドでは企画が通らなかったり、観客が楽しめなかったりするのだろう…。

#2 [nitijyou] 電動自転車のタイヤを交換

ここ最近、電動自転車の前タイヤの空気がビミョーに抜けている感じがあって。そのあたりを親父さんと相談したら、親父さんが朝方や夕方に虫ゴムを交換してくれた。が、少し走ったらまるでパンクしたかのように空気が抜けていて、どうやらこれはチューブがいかんのではという話に。タイヤの表面も結構削れて、どこもかしこもひび割れている状態だったので、これまた親父さんが近所の自転車屋まで電動自転車を持って行って、前タイヤを交換してきた。とメモ。作業代やタイヤの値段込みで、7,000円ぐらいかかったらしい。

たしか、後ろのタイヤも、随分前に親父さんが、その自転車屋さんで交換してもらっていたはず。さて、次回の交換は何時頃になることやら…。

2020/05/29(金) [n年前の日記]

#1 [nitijyou] 歯医者に行ってきた

自転車でS歯科まで。PM02:00の予約で、PM02:10-PM02:20まで治療。

2019/05/29(水) [n年前の日記]

#1 [mz][cg_tools][python] MZ-700風互換フォントのBDFやTTFを作成してみたり

ここ数日、Windows上でMZ-700風のフォントを表示できないかと夢想しつつ実験をしていたり。結果として、BDFフォントやTTFフォントを試しに作ってみた次第。あくまで実験。実用性は無いです。あるわけがない。とは言え、WindowsアプリでMZ-700風フォントが表示されてるの図は、ビミョーにちょっとクラクラできる気もしたりして。

_mieki256/mz700fon2bdf: Generate compatible font like MZ-700

上記ページの右上の「Clone or download」をクリックして zip をダウンロードして、解凍して、中から .ttf を取り出せば利用できるかと。

スクリーンショット。 :

以下は、メモ帳で、自作のMZ-700風互換フォント、Pet2015bdfを指定した場合。フォントサイズは12ptを指定。

ss_pet2015bdf.png

以下は、MZ-700フォントに見える感じの画像を変換した、Mz700bdf を指定した場合。

ss_mz700bdf.png

以下は、メイリオフォントを指定した場合。前述のフォントを指定しながら、 _特定の全角文字 を打てば、MZ-700風の図形文字を表示できることが分かるかなと。

ss_meiryo.png

注意点。フォント選択時、フォント名が出てこないのは仕様。

ss_fontselect.png

昨今のフォント選択ウインドウは、そのフォントを使ってフォント名も表示するのだけど。今回作った .ttf は一部のフォントサイズ(6, 12, 18, 24, 30pt)しか有効ではないので、フォント選択ウインドウ上で使ってるフォントサイズを指定されても、そんなフォントサイズは持ってないから、フォント名も表示されない状態になるわけで。

今回試したこと。 :

  • Python + Pillow(PIL)で、1文字8x8ドット、16x32個が並んだフォント一覧画像を読み込んで、BDF形式でテキスト出力してみたり。
  • BDFフォントを拡大して別のBDFを生成できる、bdfresize を使ってみたり。
  • 複数のBDFからビットマップフォント埋め込みTTFを作成できる、bdf2ttf を使ってみたり。

課題。 :

  • BDFからアウトラインフォントを作りつつ、そこにビットマップフォントを埋め込む作業の手順が把握できてない。
FontForge を利用して、アウトラインフォントに変換する作業は、昨日の作業で少し分かりかけてきたのだけれど。そこに、ビットマップフォントを埋め込めるのかどうか、まだ把握できてない状態。

ライセンスについて補足。 :

Pet2015bdfフォントの、英数字、カタカナ、ひらがら部分は、自分がドット打ちした部分なので、自由に使えるはずです。図形文字は、まだ一部、MZ-700のソレが残ってるけど…。

MZ-700フォント画像は、配布しちゃってもいいのか悪いのか分からんけど、とりあえず一緒に置いときました。まあ、気になる人は互換フォントだけ使えば済む話かと。

レトロPC、特にMZシリーズのフォントのライセンスは、何がアウトで何がセーフか、よくわからんのですよね…。詳しくは以下を。

_mieki256's diary - レトロPCのフォントの著作権って一体どうなっているんでしょうね

#2 [zatta][game] レバーとボタン

ネット上のニュースを眺めてたら、なんだか気になる話が。

_海外の大型格闘ゲーム大会にて特定のコントローラーが使用禁止に。背景にあるのは、“あいまいだったレギュレーション” | AUTOMATON

今後世間様に競技として認知させていきたいジャンルなのだから、ルールを厳格にしていくべき、という流れは妥当だろうと思いつつ。しかし、ゲームの入力機器の歴史を思い返すと、ちょっと複雑な気分になってしまうところもあるなー、と思えてきたりもして。

以下、思考メモ。おそらく件のニュースの話の本筋からずれてます。只の思考メモです。

レバーとボタンが正解とは限らない。 :

大昔のアーケードゲームって、レバーとボタンで必ず入力させる仕様ではなかったというか、ゲームのタイトル毎に入力機器の仕様が違っていたのが当たり前だったよなと…。パドル入力とか、レバー2本とか、色々あったような。そもそも、格ゲーの代表事例であるストリートファイターシリーズも、最初のヤツはボタンを叩く強さでアクションが変わる仕様だった気もする。 *1

本来、ゲームを快適に遊んでもらうためには、ゲーム内容に即した入力機器が提供されるべきで。だから昔のゲームは、タイトル毎に入力機器の仕様が違っているのもアリだったのだろうなと。ゲーム内容が違うのだもの、コントローラだって違って当然っしょ。みたいな。

だけど、商品が変わるごとに入力機器の仕様が変わる、筐体が必ず変わるとなると、店側は導入費用が高くついちゃうし、ゲームメーカも毎回入力機器の設計をし直す羽目になるからコストがかかるしで。使い回しができる筐体のほうが商売上は助かるよね、せめて基板の入出力コネクタぐらいは共通規格にしませんか、ということになって、業界で _規格 が作られて、てな歴史があったりもするわけで。

しかし、規格や筐体が決まり、入力機器もレバーとボタンで固まってきて、開発現場はコレを前提にしてどうにかせい、と強制されると、今度はゲームを作る側がちょっと困ってしまって。「このコントローラ仕様ではプレイヤーキャラに色んなアクションさせられないなあ。ボタンが足りない。どうしよう」「そうだ。レバーとボタンの組み合わせでコマンドを入力できるようにしてみたらどうだろう」と閃いて…。そうやって、いわゆる格ゲーというジャンルのフォーマットが固定するわけだけど。

汎用性を重視した入力機器仕様を強制されてしまったから、苦肉の策としてコマンド入力という仕様が盛り込まれた、と言えなくもないよなと。「お客さんに楽しくゲームを遊んでもらおう」と思ってそういう仕様にしたというより、「商売の都合でこうなってしまいました」てな側面のほうが大きい、そんな気もしてきたり。 *2 つまり、格ゲーとは縛りプレイである、とも言えそうな。

てなことを考えていくと、レバーとボタンだけで戦え、という方針は、これははたして格ゲーというジャンルの今後の発展を考えた場合に正しいのかどうか、ちょっと悩むなと。格ゲーは本当にそれでいいのか。実はもっと楽しく遊べる・盛り上がれる入力仕様があったりするのではないか。などと不安になってきちゃったりもして。

でもまあ、元々が縛りプレイだったジャンルだし、今更かも…。

厳しくするのも緩くするのもどちらもアリかも。 :

いわゆるeスポーツって、要は見ているお客さんが盛り上がればジャンルとして成立するのだろうと自分は想像しているのだけど。野球やサッカーもそうだし。であれば、観客を盛り上げるために各種ルールが設定されていくのが妥当であろうと。

となると、レバーとボタンだけで戦え、というルールは、見ているお客さんがより盛り上がることに繋がっていくのかどうか、という疑問も。どうなんだろう。

てなあたりからバカ妄想。格ゲーが元々縛りプレイであることを意識できたら、それを加速する方向に進むことだってできるかも。ジャンプ禁止とか、必殺技封印とか、片手操作とか、足で操作とか。そういうルール・部門だって作れなくもないよなと。そのほうが盛り上がるなら、という前提付きの話だけど。

逆の方向もアリかもしれず。何を使っても構わないからとにかく勝て、派手に戦え、みたいな。各人が色んなコントローラを使う中、レバーとボタンで攻略しちゃう達人が出てきて更に盛り上がったり。とか。

大昔にTV放映されていた鳥人間コンテスト等でも、ひたすら記録を伸ばすことに注力し続ける参加チームと、一発ネタで観客を笑わせるチームに二分していた記憶があるけれど。eスポーツも、そういうカテゴリ分けができたりしないか。ひたすら勝つことに注力する試合とは別に、絶対勝てるわけがないんだけど操作してる人の悪戦苦闘を眺めてるだけで観客大爆笑、みたいな何かというか…。

どこかのユーチューバーが、そういうことをしたりしないかな。eスポーツには絶対出れないぐらいに低レベルだけど、その人のプレイを見てるだけで皆が元気になれる、みたいな。「レバーとボタンしか使っちゃダメ」とeスポーツが固いことを言ってるのを尻目に、「今日はこんなトンデモ機器でプレイしてみました!」的動画をアップしてお客さんに喜んでもらうゲームプレイヤー。って既に居そうな気もする…。色んな人が居るもんな。絶対居るよな。

何にせよ、大昔のゲームの入力機器がバラバラだったように、ゲームのプレイの仕方も色々あったほうが楽しいんじゃないか、などと素朴なことを思ってしまったりもして。もちろん、その「色々」には、「あえてレバーとボタンだけ」や、「レバーとボタンにこだわらず」等々、何でも含まれていて…。

楽しくなるなら、どんなルートもアリだよな、と。

余談。 :

個人的には、eスポーツってどうなの、成立するのかね、と疑問視しているところもあって。

一般的なスポーツの場合、人間の肉体はちょこっと弄ればスペックが急激に変わるものではないので、じっくりと鍛えていかないと成果が出ないし、故に記録を伸ばすこと、残すことにも価値が生じるわけだけど。

しかし、ゲームって、開発スタッフがプログラム上の数値をちょっと弄るだけで、プレイヤーキャラのスペックが急激に変わったりするので ―― 競い合うための土台が、作り手という「神」の振る舞い次第で急変してしまうから、何かを競い合うという状況が成立しにくい気もするわけで。プレイヤーがどんなに訓練して技を磨いても、プログラマーが数値をちょっと弄ったら全部水の泡、では…。こんな不安定なネタで、記録云々という方向で競技らしく見せるのは、ちょっと無理があるんじゃないのと思っていたり。 *3 *4

だけど、観客を楽しませたほうが勝ち(みたいなもん)、と捉えれば、それならフツーに成立しそうだなと。もっとも、それはもはや競技ではないのかもしれない。プロレスのショーみたいなものになってしまうのだろうか。

こういうのって、「客を楽しませてなんぼ」で発展させるのか、「記録を残してなんぼ」で発展させるのか、どちらに進むかで定着するかどうかが違ってきたりするのかな、などと思ったりもして。どちらが残りやすいのかは分からんけれど。

てな感じのことをぼんやり思ってしまったのでメモ。只の思考メモです。オチはないです。

*1: しかしその仕様だとボタンが壊れてメンテナンスが大変だったから、ボタンを複数用意した版が作られたり、続編のスト2はデジタルなレバーとボタンで入力する仕様「のみ」になったのではなかったかしらん。
*2: もちろん、与えられた枠の中で、より楽しく遊んでもらいたいと考えた末に生まれた仕様だから、けして否定されるべきものではないはずで。
*3: 当然ながら、試合に使うソフトのバージョンは固定等、競技の土台がぶれないように工夫はするだろうけど、競技に使うソレと、市場で入手できるソレに大きな違いが発生したら、その場合どうなるのだろう、等の不安も。
*4: 肉体を使うスポーツも、ルールが改変されたらそれまでの努力が、ということがありえるから、一般的なスポーツも、eスポーツも、どちらも同じと捉えちゃうのもアリ、なのかも。

2018/05/29(火) [n年前の日記]

#1 [game] 斜め床についてなんだか考え込んだり

昔のアクションゲームをいくつかプレイしてみたけど、昔のゲームって斜め床はほとんど無いな…。8x8ドットのタイル(矩形)がそこにあるかないか、だけで地形を作ってるものが多いような。まあ、確認したタイトルはジャンプアクションがほとんどだったので、あまり斜め床の必要性がないのかも。

そもそも、斜め床があるとどんな遊びが盛り込めるのか。なんだか考え込んでしまったり。自機と敵のy座標が違うからジャンプしつつ敵を狙って、てな遊びは斜め床が無くても盛り込めるし…。斜め床じゃないとこういう遊びができない、みたいなことってあったかな…。

2017/05/29(月) [n年前の日記]

#1 [cg_tools] 歩きについて未だに勉強中

blenderで歩きのモーションを実験中。腕の振りを色々弄ってそれっぽくなったものの、なんだかヒロインっぽい動きになってしまったので最初から作り直し。フツーに見える歩きを探ってみたいわけで。

2016/05/29() [n年前の日記]

#1 [blender] blender + LuxRenderで実験中

blender で木を作れないか実験中だけど、もしかして _LuxRender を使ってみたら、また違うレンダリング結果が得られるのだろうかと思えてきたので試しているところ。

やっぱりリアルには程遠い気がする。何がいかんのだろう。

2015/05/29(金) [n年前の日記]

#1 [cg_tools] blenderとシンボリックリンク

Windows7 x64上で blender 2.74 x64 を触ってて気づいたのだけど。NTFSのジャンクション? シンボリックリンク? をガン無視されるようで。

ユーザ設定で何か設定する箇所があるのかと眺めてみたけど見当たらず。

_公式ビルド版 ではなくて _GraphicAll.org版 を使ってるからいかんのだろうかと思えてきたので、試しに公式ビルド版のzipをDL・解凍して試してみたけど、動作は同じでやっぱりガン無視される。

ググってみたら、 _T37619 Official Blender builds for Windows don't recognize NTFS symlinks の中で、「blenderはシンボリックリンクをサポートしないよ」「対応できるならしたいけど優先順位は低いかな」てな感じのソレに遭遇。

そうか…対応してないのか…。微妙に不便だけど、まあ、仕方ないか…。

_Dev:2.5/Source/Development/Todo/Install-OS - BlenderWiki に、
Symbolic links are not supported T37619

Dev:2.5/Source/Development/Todo/Install-OS - BlenderWiki より

って書いてあるな…。2.5の頃からサポートされてないのだな。たぶん。

他にも、 _network drives in blender and win7 で、「ネットワークドライブをサポートしてないからスタジオ内で使う3DCGソフトとして採用できねえ」てな感じの話が出てるような。なるほど、個人ならともかく、社内で共同作業するときは、そういうのって困りそうだな…。ただ、「use maped network drive」とか書いてあるから、ネットワークドライブの割り当てをすれば回避できたりするのだろうか。英語分からんです。

#2 [cg_tools] blenderでロゴ画像作成

立体的なロゴ画像を作りたいなと。以下のページを参考にして作業。ありがたや。

_Inkscape-aholic!: Inkscape+Blenderで3D化

Inkscape でロゴの形を作成。svgとして保存。blender にsvgをインポート。curveからmeshに変換。押し出しをして厚みをつける。位置調整やランプの追加をしてレンダリング。それっぽい画像ができた。

調子に乗って欲を出して、質感を追加したり、Cycles でレンダリングしてみたらハマった。白い点々ノイズがやたらと出てくる…。blenderの内蔵レンダラでレンダリングすると思ったような質感にならないしで悩み中。

後から2Dでテクスチャ載せたりしたほうが楽なのだろうか。どうしたもんか。

2014/05/29(木) [n年前の日記]

#1 [dxruby][cg_tools] DXRubyでswfのシェイプを描画する実験

とりあえず、今現在動いてるところまでメモしておこうかなと。

二次ベジェ曲線。 :

まずは、二次ベジェ曲線の描画を実験。
二次ベジェ曲線の描画テスト

_bezierdraw.rb
require 'dxruby'

# 二次ベジェ曲線を描画するクラス
class BezierDraw
  DBG = true

  # 二次ベジェ曲線を描画するための頂点リストを生成
  #
  # @param [Number] x1 始点 x 座標
  # @param [Number] y1 始点 y 座標
  # @param [Number] x2 制御点 x 座標
  # @param [Number] y2 制御点 y 座標
  # @param [Number] x3 終点 x 座標
  # @param [Number] y3 終点 y 座標
  # @return [Array] ベジェ曲線を描画するための頂点座標配列
  #
  def BezierDraw.calc(x1, y1, x2, y2, x3, y3)
    p = []
    p.push([x1, y1])
    t = 0.05
    while t < 1.0
      v = 1.0 - t
      a = v * v
      b = 2 * v * t
      c = t * t
      x = a * x1 + b * x2 + c * x3
      y = a * y1 + b * y2 + c * y3
      p.push([x, y])
      t += 0.05
    end
    p.push([x3, y3])
    return p
  end

  # ベジェ曲線を描画
  #
  # @param [Object] img Imageオブジェクト
  # @param [Array] p 頂点座標配列
  # @param [Array] lcol 色配列。A,R,G,B が入ってる。
  #
  def BezierDraw.draw(img, p, lcol)
    (p.size - 1).times do |i|
      j = i + 1
      img.line(p[i][0], p[i][1], p[j][0], p[j][1], lcol)
    end
  end
end

if $0 == __FILE__
  # ----------------------------------------
  # 動作テスト

  img = Image.new(640, 480)
  p = [[30, 240], [300, 10], [600, 400]]
  lcol = [255, 255, 0, 0]

  Window.loop do
    break if Input.keyPush?(K_ESCAPE)

    p[1] = Input.mousePosX, Input.mousePosY

    x0, y0 = p[0]
    for i in 1..2 do
      x1, y1 = p[i]
      Window.drawLine(x0, y0, x1, y1, [128, 128, 128])
      x0, y0 = x1, y1
    end

    img.clear
    x1, y1 = p[0]
    x2, y2 = p[1]
    x3, y3 = p[2]
    np = BezierDraw.calc(x1, y1, x2, y2, x3, y3)
    BezierDraw.draw(img, np, lcol)
    Window.draw(0, 0, img)
  end
end
マウスカーソルを動かすと制御点を移動できます。

凹多角形の塗りつぶし。 :

凹多角形の塗りつぶし

_polyfill.rb
require 'dxruby'

# 与えられた多角形で塗りつぶしをするクラス
#
# @note 以下のページを参考にしました。
#       多角形塗りつぶし(1)
#       http://azskyetc.client.jp/paintprog/031_polygon1.html
#
class PolyFill

  # 塗り潰しをする
  #
  # @param [Object] img Imageオブジェクト
  # @param [Array] np 頂点座標配列 ((x,y), (x,y), ...)の形で入っている。
  # @param [Array] f0col 塗り潰しに使う色配列
  # @param [Array] f1col 塗り潰しに使う色配列
  # @param [Boolean] clip_enable trueなら画面サイズを超えた部分の描画をしない
  #
  def PolyFill.fill(img, np, f0col, f1col, clip_enable = true)

    return if np.size < 3

    # y座標の最小値と最大値を求める
    ymin = ymax = np[0][1]
    np.each do |p|
      ymin = p[1] if ymin > p[1]
      ymax = p[1] if ymax < p[1]
    end

    if clip_enable
      ymin = 0 if ymin < 0
      ymax = Window.height if ymax > Window.height
    end

    if clip_enable
      # 1ラインずつスキャンしていく
      ymin.step(ymax, 1.0) do |y|
        xlst = PolyFill.get_intersection_point(y.to_f, np) # 交点のx座標を求める
        next if xlst.empty? # 交点が無い
        next if xlst.size % 2 != 0 # 交点数が奇数
        i = 0
        while i < xlst.size
          x0, x1 = xlst[i], xlst[i+1]
          unless x1 < 0 or x0 > Window.width
            img.line(x0, y, x1, y, f0col)
          end
          i += 2
        end
      end
    else
      ymin.step(ymax, 1.0) do |y|
        xlst = PolyFill.get_intersection_point(y.to_f, np)
        next if xlst.empty? or xlst.size % 2 != 0
        i = 0
        while i < xlst.size
          img.line(xlst[i], y, xlst[i+1], y, f0col)
          i += 2
        end
      end
    end
  end

  # 与えられた頂点座標配列を元にして交点リストを求める
  #
  # @param [Number] y スキャンするy座標
  # @param [Array] lst 頂点座標配列
  # @return [Array] 交点のx座標を配列で返す
  #
  def PolyFill.get_intersection_point(y, lst)
    xlst = []
    len = lst.size
    len.times do |i|
      x1, y1 = lst[i]
      x2, y2 = lst[(i + 1) % len]

      next if y1 == y2 # 水平線なら処理しない

      # yが、現在の辺の終点と、次辺の始点であり、
      # 両辺が上方向、または下方向の場合は交点から除外
      if y == y2
        y3 = lst[(i + 2) % len][1]
        next if (y2 - y1 < 0 and y3 - y2 < 0)
        next if (y2 - y1 > 0 and y3 - y2 > 0)
      end

      # yが下方向になるように入れ替え
      if y1 > y2
        x1, x2 = x2, x1
        y1, y2 = y2, y1
      end

      if y1 <= y and y <= y2
        # 交点を追加
        x = ((y - y1) * (x2 - x1)).to_f / (y2 - y1) + x1
        xlst.push(x)
      end
    end

    # 交点を小さい順にソートして返す
    return xlst.sort
  end
end

if $0 == __FILE__
  # ----------------------------------------
  # 動作テスト

  img = Image.new(640, 480)
  lst = [
    [200, 30],
    [300, 130],
    [350, 230],
    [300, 330],
    [200, 230],
    [50, 330],
    [100, 130],
    [200, 30]
  ]
  f0col = [255, 0, 255, 0]
  f1col = [255, 255, 0, 0]

  Window.loop do
    break if Input.keyPush?(K_ESCAPE)
    lst[4] = Input.mousePosX, Input.mousePosY
    img.clear
    PolyFill.fill(img, lst, f0col, f1col, false)
    Window.draw(0, 0, img)
  end
end
マウスカーソルを動かすと1点だけ移動できます。

_多角形塗りつぶし(1) をそのまま DXRuby で動くように書き直しただけですが…。

アンチエイリアス付きの直線描画。 :

_Xiaolin Wu's line algorithm - Wikipedia, the free encyclopedia を手元でも実験。

_Wu Anti-aliased Lines
_Xiaolin Wu's line algorithm - Rosetta Code
_Antialiasing: Wu Algorithm - CodeProject

アンチエイリアス付きの直線描画

ちなみに、アンチエイリアス無し(DXRuby の Image#line)で描画すると以下のような感じに。
アンチエイリアス無しの直線描画

_xiaolinwu.rb
# Xiaolin Wu's line algorithm - Rosetta Code
# http://rosettacode.org/wiki/Xiaolin%5FWu%27s%5Fline%5Falgorithm

require 'dxruby'

class XiaolinWuDraw

  def XiaolinWuDraw.draw_line(img, x1, y1, x2, y2, colour)
    if x1 == x2 and y1 == y2
      # not line. this is a dot.
      img[x1, y1] = colour
      return
    end

    dx, dy = x2 - x1, y2 - y1
    steep = (dy.abs > dx.abs)? true : false
    x1, y1, x2, y2, dx, dy = y1, x1, y2, x2, dy, dx if steep
    x1, y1, x2, y2 = x2, y2, x1, y1 if x1 > x2
    gradient = dy.to_f / dx.to_f

    # handle the first endpoint
    xend = x1.round
    yend = y1 + gradient * (xend - x1)
    fp = (x1 + 0.5) - (x1 + 0.5).truncate
    rfp = 1.0 - fp
    xgap = rfp
    xpxl1 = xend
    ypxl1 = yend.truncate
    fp = yend - yend.truncate
    rfp = 1.0 - fp
    XiaolinWuDraw.put_colour(img, xpxl1, ypxl1,     colour, steep, rfp * xgap)
    XiaolinWuDraw.put_colour(img, xpxl1, ypxl1 + 1, colour, steep,  fp * xgap)
    itery = yend + gradient

    # handle the second endpoint
    xend = x2.round
    yend = y2 + gradient * (xend - x2)
    fp = (x2 + 0.5) - (x2 + 0.5).truncate
    rfp = 1.0 - fp
    xgap = rfp
    xpxl2 = xend
    ypxl2 = yend.truncate
    fp = yend - yend.truncate
    rfp = 1.0 - fp
    XiaolinWuDraw.put_colour(img, xpxl2, ypxl2,     colour, steep, rfp * xgap)
    XiaolinWuDraw.put_colour(img, xpxl2, ypxl2 + 1, colour, steep,  fp * xgap)

    # in between
    (xpxl1 + 1).upto(xpxl2 - 1).each do |x|
      itt = itery.truncate
      fp = itery - itery.truncate
      rfp = 1.0 - fp
      XiaolinWuDraw.put_colour(img, x, itt,     colour, steep, rfp)
      XiaolinWuDraw.put_colour(img, x, itt + 1, colour, steep,  fp)
      itery = itery + gradient
    end
  end

  def XiaolinWuDraw.put_colour(img, x, y, col, steep, c)
    return if c == 0.0 or col[0] == 0
    x, y = y, x if steep
    o = img[x, y]
    n = Array.new(4)
    if o[0] >= 255
      # Bg Alpha = 255
      n[0] = 255
      for i in 1..3 do
        n[i] = (col[i] * c + o[i] * (1.0 - c)).round
      end
    elsif o[0] == 0
      # Bg Alpha = 0
      n[0] = (255 * c).round
      for i in 1..3 do
        n[i] = col[i]
      end
    else
      na = (255 * c).round
      n[0] = (na > o[0])? na : o[0]
      for i in 1..3 do
        n[i] = (col[i] * c + o[i] * (1.0 - c)).round
      end
    end
    img[x, y] = n
  end
end

# ----------------------------------------
# test

if $0 == __FILE__
  font = Font.new(14)

  w, h = 500, 500
  bgcol = [0, 0, 255] # blue (R,G,B)
  fgcol = [255, 255, 255, 0] # Yellow (A,R,G,B)
  fgcol2 = [255, 0, 255, 0] # Green (A,R,G,B)

  p = []
  10.step(460, 30) do |a|
    p.push([10, 10, 490, a, fgcol])
    p.push([10, 10, a, 490, fgcol])
  end
  p.push([10, 10, 490, 490, fgcol])

  img0 = Image.new(w, h)
  # img0.fill(bgcol)
  p.each do |d|
    x1, y1, x2, y2, col = d
    XiaolinWuDraw.draw_line(img0, x1, y1, x2, y2, col)
  end
  # img0.save("test.png")

  img1 = Image.new(w, h)
  p.each do |d|
    x1, y1, x2, y2, col = d
    img1.line(x1, y1, x2, y2, col)
  end

  img2 = Image.new(640, 480)

  Window.bgcolor = bgcol
  Window.loop do
    break if Input.keyPush?(K_ESCAPE)

    # Push A key
    aa_enable = (Input.keyDown?(K_A))? false : true

    img2.clear
    x1, y1 = 320, 240
    x2, y2 = Input.mousePosX, Input.mousePosY

    if aa_enable
      XiaolinWuDraw.draw_line(img2, x1, y1, x2, y2, fgcol2)
      Window.draw(0, 0, img0)
      Window.draw(0, 0, img2)
    else
      img2.line(x1, y1, x2, y2, fgcol2)
      Window.draw(0, 0, img1)
      Window.draw(0, 0, img2)
    end

    s = "#{Window.real_fps} FPS  CPU: #{Window.getLoad.to_i} %"
    Window.drawFont(640 - 140, 2, s, font)
    s = "Push A key"
    Window.drawFont(640 - 140, 20, s, font)
  end
end
一見それらしく描画できたものの、アルファチャンネル値の扱いに関してバグが残ってるような気がします…。

直線描画。 :

色々なやり方で直線を描画してみたり。

直線描画

_linedraw.rb
require 'dxruby'
require_relative 'xiaolinwu'

#
# 直線を描画するクラス
#
class LineDraw

  # 直線を描画
  #
  # @param [Object] img 描画対象のImageオブジェクト
  # @param [Number] x1 直線始点 x
  # @param [Number] y1 直線始点 y
  # @param [Number] x2 直線終点 x
  # @param [Number] y2 直線終点 y
  # @param [Array] col 描画色配列 A,R,G,B
  # @param [Number] linew 線幅
  # @param [Number] aa アンチエイリアス処理の分割数
  # @param [Number] last_t 前回描画時の余った値
  # @param [Boolean] aa2 trueなら線幅が太い場合もアンチエイリアスをかけるが激しく遅い
  # @param [Boolean] edge_only trueならエッジのみ描画。動作確認用
  # @return [Number] 描画時の余った値
  #
  def LineDraw.draw(img, x1, y1, x2, y2, col, linew = 1,
                    aa = 1, last_t = 0, aa2 = false, edge_only = false)
    ret = 0
    if linew <= 1
      # 線幅 = 1 の時

      if aa <= 1
        # アンチエイリアス無し
        LineDraw.draw_dda(img, x1, y1, x2, y2, col)
        # img.line(x1, y1, x2, y2, col)
      else
        # アンチエイリアス有り
        XiaolinWuDraw.draw_line(img, x1, y1,x2, y2, col)
      end
    else
      # 線幅 > 1 の時

      if aa2
        # アンチエイリアス有りで描画。激しく遅い
        ret = LineDraw.draw_aa(img, x1, y1, x2, y2, col, linew, aa, last_t)
      else
        # アンチエイリアス無しで描画

        # 三角形ポリゴン+円塗りつぶしで描画
        ret = LineDraw.draw_poly(img, x1, y1, x2, y2, col, linew, edge_only)

        # ブラシで描画
        # ret = LineDraw.draw_brush(img, x1, y1, x2, y2, col, linew, last_t)
      end
    end
    return ret
  end

  # ----------------------------------------
  # 直線をDDAで描画。アンチエイリアス無し
  #
  # @note 以下参考ページ
  #       DDAによる線・円の描画3
  #       http://www7.plala.or.jp/nekogrammer/dda/DDA3.htm
  #
  # @param [Object] img 描画対象のImageオブジェクト
  # @param [Number] x1 直線始点 x
  # @param [Number] y1 直線始点 y
  # @param [Number] x2 直線終点 x
  # @param [Number] y2 直線終点 y
  # @param [Array] col 描画色配列。A,R,G,B
  #
  def LineDraw.draw_dda(img, x1, y1, x2, y2, col)
    x1 = x1.to_i
    y1 = y1.to_i
    x2 = x2.to_i
    y2 = y2.to_i
    dx = x2 - x1
    dy = y2 - y1
    a = dx.abs
    b = dy.abs
    xadd = LineDraw.get_sign(dx)
    yadd = LineDraw.get_sign(dy)
    x, y = x1, y1
    if a >= b
      # x方向のほうが大きい
      e = dy.abs * -1
      fg = true
      while fg
        img[x, y] = col
        break if x == x2
        x += xadd
        e += 2 * b
        if e >= 0
          y += yadd
          e -= 2 * a
        end
      end
    else
      # y方向のほうが大きい
      e = dx.abs * -1
      fg = true
      while fg
        img[x, y] = col
        break if y == y2
        y += yadd
        e += 2 * a
        if e >= 0
          x += xadd
          e -= 2 * b
        end
      end
    end
    return 0
  end

  def LineDraw.get_sign(x)
    return 0 if x == 0
    return -1 if x < 0
    return 1
  end

  # ----------------------------------------
  # 直線をブラシ画像で描画
  #
  # @param [Object] img 描画対象のImageオブジェクト
  # @param [Number] x1 直線始点 x
  # @param [Number] y1 直線始点 y
  # @param [Number] x2 直線終点 x
  # @param [Number] y2 直線終点 y
  # @param [Array] col 描画色配列 A,R,G,B
  # @param [Number] linew 線幅
  # @param [Number] last_t 前回描画時の余った値
  # @param [Number] line_interval 描画間隔
  # @return [Number] 描画時の余った値
  #
  def LineDraw.draw_brush(img, x1, y1, x2, y2, col, linew,
                          last_t = 0, line_interval = 0.2)

    brush = LineDraw.get_brush_image(col, linew, aa = 4)
    dx = (x2 - x1).to_f
    dy = (y2 - y1).to_f
    len = Math.sqrt(dx * dx + dy * dy)
    return if len == 0
    ti = line_interval / len
    t = last_t / len
    r = brush.width / 2
    while t < 1.0
      x = dx * t + x1 - r
      y = dy * t + y1 - r
      img.draw(x, y, brush)
      dt = r * ti
      dt = 0.0001 if dt < 0.0001
      t += dt
    end
    last_t = len * (t - 1.0)
    brush.dispose
    return last_t
  end

  # 描画用のブラシImageを取得
  #
  # @param [Array] col ブラシ色
  # @param [Number] linew 線幅
  # @param [Number] aa アンチエイリアス値
  # @return [Object] ブラシ用Image
  #
  def LineDraw.get_brush_image(col, linew, aa = 9)
    w, h = linew, linew
    r = linew / 2.0
    if w <= 0 or h <= 0
      w, h = 1, 1
      r = 0.5
    end
    img = Image.new(w, h)
    rr = r * r
    aad = aa * aa
    0.step(h, 1.0) do |y|
      0.step(w, 1.0) do |x|
        v = 0
        aa.times do |jy|
          yy = jy * (1.0 / aa) + y - r
          aa.times do |jx|
            xx = jx * (1.0 / aa) + x - r
            d = (xx * xx + yy * yy) / rr
            v += (1.0 - d) if d < 1.0
          end
        end
        a = col[0] * v.to_f / aad
        img[x, y] = [a, col[1], col[2], col[3]]
      end
    end
    return img
  end

  # ----------------------------------------
  # 直線をアンチエイリアス有りで描画
  #
  # @note 以下参考ページ
  #       アンチエイリアス付きの自由線描画(1)
  #       http://azskyetc.client.jp/paintprog/025_aaline1.html
  #
  # @param [Object] img 描画対象のImageオブジェクト
  # @param [Number] x1 直線始点 x
  # @param [Number] y1 直線始点 y
  # @param [Number] x2 直線終点 x
  # @param [Number] y2 直線終点 y
  # @param [Array] col 描画色配列 A,R,G,B
  # @param [Number] linew 線幅
  # @param [Number] aa アンチエイリアス処理の分割数
  # @param [Number] last_t 前回描画時の余った値
  # @param [Number] line_interval 描画間隔
  # @return [Number] 描画時の余った値
  #
  def LineDraw.draw_aa(img, x1, y1, x2, y2, col, linew,
                       aa = 4, last_t = 0, line_interval = 0.25)
    dx = (x2 - x1).to_f
    dy = (y2 - y1).to_f
    len = Math.sqrt(dx * dx + dy * dy)
    return if len == 0
    ti = line_interval / len
    t = last_t / len
    while t < 1.0
      x = dx * t + x1
      y = dy * t + y1
      LineDraw.draw_point(img, x, y, col, linew, aa)
      dt = linew * ti
      dt = 0.0001 if dt < 0.0001
      t += dt
    end
    last_t = len * (t - 1.0)
    return last_t
  end

  # アンチエイリアス付きで円を描画
  #
  # @param [Object] img Imageオブジェクト
  # @param [Number] px x座標
  # @param [Number] py y座標
  # @param [Array] col 描画色配列。A,R,G,B
  # @param [Number] linew 線幅
  # @param [Number] aa アンチエイリアス処理の分割数
  #
  def LineDraw.draw_point(img, px, py, col, linew, aa = 4)
    r = linew / 2.0
    x1, y1 = (px - r).floor, (py - r).floor
    x2, y2 = (px + r).ceil, (py + r).ceil
    rr = r * r
    aad = aa * aa
    cc = [255, col[1].to_i, col[2].to_i, col[3].to_i]
    for y in y1..y2
      for x in x1..x2
        next if img.compare(x,y,cc)

        v = 0.0
        xa = x - px
        ya = y - py
        for jy in 0..aa
          yy = ya + (jy.to_f / aa)
          for jx in 0..aa
            xx = xa + (jx.to_f / aa)
            d = (xx * xx + yy * yy) / rr
            v += (1.0 - d) if d < 1.0
          end
        end
        ao = col[0] * v / aad
        ao = 0 if ao < 0
        ao = 255.0 if ao > 255.0

        s = img[x,y]
        s[0] = (s[0] > ao)? s[0] : ao
        a = ao / 255.0
        ma = 1.0 - a
        s[1] = s[1] * ma + cc[1] * a
        s[2] = s[2] * ma + cc[2] * a
        s[3] = s[3] * ma + cc[3] * a
        img[x,y] = s
      end
    end
  end

  # ----------------------------------------
  # 三角形塗りつぶしと円塗りつぶしを使って直線を描画
  #
  # @note 線本体を三角形塗りつぶしを2回使って描く。始点と終点は円塗りつぶしで描く。
  #
  # @param [Object] img 描画対象のImageオブジェクト
  # @param [Number] x1 直線始点 x
  # @param [Number] y1 直線始点 y
  # @param [Number] x2 直線終点 x
  # @param [Number] y2 直線終点 y
  # @param [Array] col 描画色配列 A,R,G,B
  # @param [Number] linew 線幅
  # @param [Boolean] edge_only trueならエッジのみ描画。動作確認用
  # @return [Number] 描画で余った値
  #
  def LineDraw.draw_poly(img, x1, y1, x2, y2, col, linew, edge_only = false)
    r = linew / 2.0
    dx = x2 - x1
    dy = y2 - y1
    rad = Math.atan2(dy, dx) + (Math::PI / 2.0)
    xd = r * Math.cos(rad)
    yd = r * Math.sin(rad)

    # 線幅を持った線、つまり、矩形の4点を求める
    np = []
    np.push([x1 + xd, y1 + yd])
    np.push([x2 + xd, y2 + yd])
    np.push([x2 - xd, y2 - yd])
    np.push([x1 - xd, y1 - yd])

    if edge_only
      # エッジだけ描画して動作確認
      np.size.times do |i|
        x3, y3 = np[i]
        x4, y4 = np[(i+1) % np.size]
        img.line(x3, y3, x4, y4, col)
      end
      img.circle(x1, y1, r, col)
      img.circle(x2, y2, r, col)
    else
      # 塗り潰し

      # 三角形塗りつぶしを2回
      img.triangleFill(np[0][0], np[0][1], np[1][0], np[1][1],
                       np[2][0], np[2][1], col)
      img.triangleFill(np[2][0], np[2][1], np[3][0], np[3][1],
                       np[0][0], np[0][1], col)
      # 始点と終点を円で塗りつぶし
      img.circleFill(x1, y1, r, col)
      img.circleFill(x2, y2, r, col)
    end

    return 0
  end

end

if $0 == __FILE__
  # ----------------------------------------
  # 動作テスト

  font = Font.new(14)
  img = Image.new(640, 480)
  col = [255, 0, 255, 0]
  p = [
    [
      [58.15, 39.0],
      [58.15, 230.1],
      [171.1, 230.1],
      [171.1, 39.0],
      [58.15, 39.0]
    ],
    [
      [20.0, 240.0],
      [100.0, 300.0],
      [600.0, 400.0]
    ]
  ]

  linew = 1
  aa = 1
  aa2 = false
  list_kind = 0
  point_mv = false
  edge_only = false

  # Window.scale = 2
  Window.bgcolor = [128, 128, 128]

  Window.loop do
    break if Input.keyPush?(K_ESCAPE)

    # Eキーで塗りつぶし/エッジのみ描画を切替
    edge_only = !edge_only if Input.keyPush?(K_E)

    # 上下キーで線幅を変更
    linew += 0.5 if Input.keyPush?(K_UP)
    linew -= 0.5 if Input.keyPush?(K_DOWN)
    linew = 1 if linew < 1

    # Aキーで、ブラシ描画/アンチエイリアス描画の切り替え
    aa = ((aa == 1)? 3 : 1) if Input.keyPush?(K_A)

    # Sキーで、線幅が太い時もアンチエイリアス描画
    aa2 = !aa2 if Input.keyPush?(K_S)

    # Kキーで、座標配列を切替
    list_kind = (list_kind + 1) % p.size if Input.keyPush?(K_K)

    # Mキーで、座標のマウス移動を切替
    point_mv = !point_mv if Input.keyPush?(K_M)
    if point_mv
      p[list_kind][1][0] = Input.mousePosX
      p[list_kind][1][1] = Input.mousePosY
    end

    img.clear
    (p[list_kind].size - 1).times do |i|
      x0, y0 = p[list_kind][i]
      x1, y1 = p[list_kind][(i+1) % p[list_kind].size]
      LineDraw.draw(img, x0, y0, x1, y1, col, linew,
                    aa, 0, aa2, edge_only)
    end

    Window.draw(0, 0, img)

    s = "LineWidth=#{linew}  #{Window.real_fps} FPS  CPU: #{Window.getLoad.to_i}%"
    Window.drawFont(8, 2, s, font)
    s = "A , S , K , E , M , up , down key"
    Window.drawFont(8, 16, s, font)
  end
end
  • 上下キー : 線幅の増減
  • Kキー : 描画する形状を変更
  • Mキー : 1点だけマウスカーソルで移動
  • Aキー : (線幅が1の時) アンチエイリアスの有効無効
  • Eキー : (線幅が1より大きい時) エッジだけ描画するか、塗り潰すか
  • Sキー : (線幅が1より大きい時) アンチエイリアスの有効無効 (※ 滅茶苦茶重い)
線幅有りでアンチエイリアスを有効にすると、フリーズしたかと思うぐらいに遅くなります。ここをどうにかしたいけど…。

ソース中で、以下の描画方法を試してます。
  • DDA : 1ドット幅、アンチエイリアス無。
  • Xiaolin Wu's line algorithm : 1ドット幅、アンチエイリアス有。(xiaolinwu.rb を利用)
  • 三角形塗りつぶし+円塗りつぶし : 線幅有、アンチエイリアス無。
  • ブラシ画像 : 線幅有、なんちゃってアンチエイリアス有。
  • オーバーサンプリング : 線幅有、アンチエイリアス有。

オーバーサンプリングを使った描画は、 _アンチエイリアス付きの自由線描画(1) をそのまま Ruby で書いてみました。さすがに Ruby でやると遅い…。

swfmillでswf→xml変換したxmlを読み込んでシェイプを描画。 :

xmlの解析に、 _Nokogiri が必要です。

(※ 2014/05/30追記。Nokogiri をインストールする前に、最新版の mini_portile をインストールしないと、Nokogiri のインストールに失敗する模様 )

シェイプを描画

_shapeparse.rb
require 'nokogiri'
require 'dxruby'
require_relative 'polyfill'
require_relative 'bezierdraw'
require_relative 'linedraw'

# swfのシェイプを解析してImageに描画するクラス
class ShapeParse
  DBG = false
  DBG2 = true
  TWIP = 20.0
  attr_accessor :id
  attr_accessor :width
  attr_accessor :left
  attr_accessor :top
  attr_accessor :height
  attr_accessor :image
  attr_accessor :draw_data
  attr_accessor :clip_enable

  def initialize(node, clip_enable = true)
    self.clip_enable = clip_enable
    self.id = node["objectID"].to_i
    puts "id[#{self.id}] #{node.name}" if DBG

    n = node.at(".//bounds/Rectangle")
    self.left = n["left"].to_i / ShapeParse::TWIP
    self.top = n["top"].to_i / ShapeParse::TWIP
    self.width = n["right"].to_i / ShapeParse::TWIP
    self.height = n["bottom"].to_i / ShapeParse::TWIP
    puts "size : (x,y)=#{self.left},#{self.top} (w,h)=#{self.width},#{self.height}" if DBG

    self.width = Window.width if self.width < Window.width
    self.height = Window.height if self.height < Window.height

    self.image = Image.new(self.width, self.height)

    x0, y0 = 0, 0
    x1, y1 = 0, 0
    x2, y2 = 0, 0
    f0_enable = true
    f1_enable = true
    l_enable = true
    fc = [[0, 0, 0, 0], [0, 0, 0, 0]]
    lc = [0, 0, 0, 0]
    lwidth = ShapeParse::TWIP
    lines = []
    self.draw_data = []

    n = node.at(".//shapes/Shape/edges").child

    while n != nil
      case n.name
      when "ShapeSetup"
        unless lines.empty?
          save_draw_data(lines, f0_enable, f1_enable, l_enable,
                         lwidth, fc[0], fc[1], lc)
          lines = []
        end

        s = "#{n.name} "
        x0 = n["x"].to_f if n.key?("x")
        y0 = n["y"].to_f if n.key?("y")
        f0_enable = (n["fillStyle0"] == "1")? true : false
        f1_enable = (n["fillStyle1"] == "1")? true : false
        l_enable =  (n["lineStyle"] == "1")? true : false

        if false
          s += "(x,y)=#{x0/TWIP}, #{y0/TWIP} ("
          s += (f0_enable)? "f0 " : "   "
          s += (f1_enable)? "f1 " : "   "
          s += (l_enable)? "l" : " "
          s += ")"
          puts s
        end

        n.xpath(".//fillStyles").each do |nn|
          nn.xpath(".//Solid/color/Color").each_with_index do |m, i|
            fc[i] = get_color(m)
          end
        end

        n.xpath(".//lineStyles").each do |nn|
          nn.xpath(".//LineStyle").each do |m|
            lwidth = m["width"].to_i if m.key?("width")
            m.xpath(".//color//Color").each do |c|
              lc = get_color(c)
            end
          end
        end

        if n.key?("x") and n.key?("y")
          lines.push([x0, y0])
        end

      when "CurveTo"
        # 二次ベジェ曲線
        x1 = x0 + n["x1"].to_f
        y1 = y0 + n["y1"].to_f
        x2 = x1 + n["x2"].to_f
        y2 = y1 + n["y2"].to_f
        lst = BezierDraw.calc(x0, y0, x1, y1, x2, y2)
        lines.concat(lst.slice(1..-1))
        x0 = x2
        y0 = y2

      when "LineTo"
        # 直線
        x1 = x0 + n["x"].to_f
        y1 = y0 + n["y"].to_f
        lines.push([x1, y1])
        x0 = x1
        y0 = y1

      else
        puts "!! Unknown Tag : #{n.name}"
      end
      n = n.next
    end

    draw(false)
  end

  # 色配列を取得
  #
  # @param [Object] node 「Color」ノード
  # @return [Array] A,R,G,Bが入った配列
  #
  def get_color(node)
    col = [255, 0, 0, 0] # ARGB
    ["alpha", "red", "green", "blue"].each_with_index do |s,i|
      col[i] = node[s].to_f if node.key?(s)
    end
    return col
  end

  # 描画用の直線データを記録
  #
  # @param [Array] lines 直線データ配列
  # @param [Boolean] fe0 塗り潰し0をするか否か
  # @param [Boolean] fe1 塗り潰し1をするか否か
  # @param [Boolean] le 線を描くか否か
  # @param [Number] lw 線幅
  # @param [Array] fc0 塗り潰し0の色配列
  # @param [Array] fc1 塗り潰し1の色配列
  # @param [Array] lc1 線描画の色配列
  #
  def save_draw_data(lines, fe0, fe1, le, lw, fc0, fc1, lc)
    np = []
    ox, oy = nil, nil
    lines.each do |p|
      x, y = p
      x /= TWIP
      y /= TWIP
      np.push([x, y]) if x != ox or y != oy
      ox, oy = x, y
    end

    # 記録
    self.draw_data.push([np, fe0, fe1, le, lw, fc0.dup, fc1.dup, lc.dup])
  end

  # Imageオブジェクトに描画
  #
  # @param [Boolean] clear_enable trueならImageをクリアしてから描画
  #
  def draw(clear_enable = true, scale_x = 1.0, scale_y = 1.0)
    self.image.clear if clear_enable

    self.draw_data.each do |d|
      p, fe0, fe1, le, lw, fc0, fc1, lc = d
      np = []
      p.each { |q| np.push([q[0] * scale_x, q[1] * scale_y]) }
      draw_line(self.image, np, fe0, fe1, le, lw, fc0, fc1, lc)
    end
  end

  # 多角形を描画
  #
  # @param [Object] img Imageオブジェクト
  # @param [Array] p 頂点座標が入った配列。
  # @param [Boolean] f0_enable trueなら塗り潰し有、falseなら塗り潰し無
  # @param [Boolean] f1_enable trueなら塗り潰し有、falseなら塗り潰し無
  # @param [Boolean] l_enable trueなら線を描く、falseなら線を描かない
  # @param [Number] lwidth 線幅
  # @param [Array] fc0 色配列。A,R,G,B
  # @param [Array] fc1 色配列。A,R,G,B
  # @param [Array] lc 色配列。A,R,G,B
  #
  def draw_line(img, p, f0_enable, f1_enable, l_enable,
                lwidth, fc0, fc1, lc)
    if f0_enable and p.size >= 3
      # 塗り潰しを行う
      PolyFill.fill(img, p, fc0, fc1, self.clip_enable)
    end

    if l_enable
      # 線描画を行う
      (p.size - 1).times do |i|
        x0, y0 = p[i]
        x1, y1 = p[(i+1) % p.size]
        LineDraw.draw(img, x0, y0, x1, y1, lc, lwidth / TWIP,
                      3, 0, false, false)
      end
    end
    lines = []
  end
end

if $0 == __FILE__
  # ----------------------------------------
  # 動作テスト

  font = Font.new(14)

  # swfmillで swf → xml変換したxmlを解析

  # infile = "swfdata/test_pdr1.xml"
  infile = "swfdata/test_pdr2.xml"

  doc = Nokogiri::XML(File.open(infile)) {|cfg| cfg.noblanks}

  objs = Hash.new
  doc.xpath("//DefineShape3").each do |node|
    pdr = ShapeParse.new(node, false) # ベクターデータを解析して画像化
    objs[pdr.id] = pdr
  end

  redraw_fg = false
  ang = 0
  scale = 1.0

  Window.bgcolor = [0, 190, 118]
  Window.fps = 60

  # メインループ
  Window.loop do
    break if Input.keyPush?(K_ESCAPE)

    # Rキー押しでスケールを変えて再描画
    redraw_fg = false
    redraw_fg = true if Input.keyDown?(K_R)

    objs.each_value do |o|
      # ベクターデータを再描画できなくもないが、遅くて実用にならない
      o.draw(true, scale, scale) if redraw_fg

      Window.draw(0, 0, o.image)
    end

    s = "#{Window.real_fps} FPS / CPU: #{Window.getLoad.to_i}%"
    Window.drawFont(4, 4, s, font)

    ang += 10
    scale = Math.cos(ang * Math::PI / 180.0) + 1.5
  end
end
  • Rキー : 押してる間、ベクターデータ(シェイプ)を、大きさを変えて再描画。数秒無反応になるぐらいに遅い。
虎のxml (test_pdr2.xml) を使うと、描画されるまで数秒待たされます…。 test_pdr1.xml なら、すぐに描画されますが、それでも、60FPSでリアルタイム描画するのは全然無理でした。

一応、データ群も一緒にまとめて zip で置いときます。

_swf_shape_parse_20140529.zip (432KB)

ここまで書いといてアレだけど。 :

swfのベクターデータを描画する処理に関しては、Ruby で書いてる限り、速度の問題で、実用性は無いなと痛感していたり。Flash Player なら一瞬で表示されるものが、Ruby + DXRuby では数秒かかるわけで。自分の実装がヒドイだけかもしれませんが。

でも、描画アルゴリズムの勉強・動作確認としてはアリかなと思いつつ。

#2 [nitijyou] 自転車で買い物に

リオンドールで夜食等を購入。

ホームセンター サンデーで犬を繋ぐためのワイヤーを購入。1.3mもあればなんとかなるかなと思ったけど、帰宅後封を切ってみたら意外と短かった。

2013/05/29(水) [n年前の日記]

#1 [cg_tools][neta] 手描きの絵の上に3DCGモデルを配置するソレについて夢想

こういうことができたりしないかなあ、とバカ妄想。

操作イメージ


こんな感じにサクサク配置できれば、進撃の巨人のアニメーターさんがナントカ装置をわざわざ手描きせずに済むんじゃないのかな…。でもまあ、今時の3DCGソフト ―― アニメ制作の現場で使われるソフトなら、きっと何十万円もするのだろうし、こういうことできんじゃないの? とも思いますが。実際はどうなんだろう。

2つの疑問点。 :

前述のgifアニメを作ってて、疑問も湧いたり。

コレ、技術的に可能なんですかね…?

例えばコレが手描きのパース図なら、4つの点座標から、消失点を2つ+モデルの中心点、を求めるところまでは可能でしょうけど。
消失点は2次元座標の計算でも求められるはず
パース定規機能がついてるお絵描きソフトなら、似たようなことができた記憶もあるし。ただ、2点透視ならともかく、3点透視で描画したいなら、線分の指定がもうちょい欲しいのではないか、3つ目の消失点も必要になったりしないかと。…まあ、そこは、2点透視+画面の回転(Z軸の回転?)で済ませちゃう、という制限を設ければなんとかなるのかな? しかしどうせなら、3点透視の見た目にしたいですわな…。そもそも手描きのパース図を描く時の手順を、いかにもな3DCGの計算に変換できるのかしら? どんな計算をすればいいのやら。

もう一点。コレ、絵描きさんにとって、本当に楽な指定の仕方になるのかねえ? と。

絵描きさんにとっては、まだ箱を描くほうが楽だったりしないかと。ただ、おそらく、箱を描いて指定するなら、厳密な描き順を要求されそうな予感も。どの線が「前」なのか。どの線が「奥行」なのか。そういうところを描き順で規定するはず。すると途端に面倒臭くなる。やってられないよなと。

ひょっとすると、3DCGを専門にやってる人ならば、「まだこういうマルチョンのほうが俺達楽だよ」「こういうガイドが描いてあれば、全キャラのアイテムを逐一配置していくのも夢じゃないね」てな別の解もあるのかなと想像したりもして。自分は3DCGに詳しくないので、イメージが湧かないですが。

技術的にできるのか。手順として本当に楽なのか/使ってもらえそうなのか。そのあたり怪しいなあ、と思ったのでした。

後者はともかく前者については、プログラマーに対するクイズみたいなもんですな…。こういう仕様を実現してくれと言われたら、自分は馬鹿だから頭抱えますけど。どうやればいいんだ、コレ。

実写と3DCGの合成テクニックが流用できないものかと。 :

_C4D 3Dオブジェクトを実写に合成したいのだ… プラグインPhotoMatchがなくても、ある程度カメラを調整: 村人とC4D
_C4D 3Dオブジェクトを実写に合成したいのだ… 消失点が背景画像の外にある場合はどうするんだい…: 村人とC4D

上記の記事では、実写と合成するための座標軸の設定を、手作業でやってるわけですけど。コレを自動でやれたら…基準になる矩形を描くだけで座標系をぐるりと合わせてくれたら、随分楽になりそうだなと夢想するわけですよ。…自動的にやってくれるプラグインとか無いのかな。いや。単に自分が無知なだけで、当たり前のように存在してそうな気も。

実写合成の場合、マッチムーブだかトラッキングだか、そういう技術が使われるそうですけど。そういうのって、アニメ制作にも流用できないんですかね…。と思ってググってみたら。

_カメラトラッキングからマッチムーブまでをAfter Effectsで自動処理するプラグイン:CameraTracker on Vimeo

凄いな…。コレ、手描きアニメには使えないのかな。だけど手描きアニメって、カメラで撮影したような厳密な絵にはなってないから、おかしな結果になったり…いや…どうなんだろう…。

余談。CLIP STUDIO PAINTを触ってみて。 :

前述のgifアニメの元画像は、CLIP STUDIO PAINT で作ったのですけど。3DCGモデルをD&Dして回転させた際にゲンナリしてしまったり。角度で見え方を調整していくのはやはりシンドイなと。ココにこの方向で置きたいのに、何故そっちを向く…!? みたいな。このあたり、何かいい手はないものかと。

もっとも、CLIP STUDIO PAINT のソレは、あくまで下絵の参考用として描画するソレだから、3DCGをポンポン置いてく作業を改善してもあまり意味は無いような気も。大量の画像を扱わなければいけないソフトでは、そういう改善も必要になるのかもしれないけど。

そういや、コミPo!の体験版を触った時も、似たような違和感があったような。漫画のネーム描く時に、こんな手順を要求されるかなあ? フツーはマルチョンでやるもんじゃないの? みたいな。

一時期、3DCGソフトが流行りそうだったのに今一つ流行らなかったわけですけど。なんかこのあたりも絡んでそうな気もするのでした。フツーの人は、目の前の物体が、x、y、z軸上でどのくらいの角度で置かれているか、なんて考えながら生活してないわけですし…。

#2 [zatta] 国連科学委員会ってどういう組織なんだろう

_原発事故 国連委「健康影響考えにくい」 NHKニュース

ニュースを見て、頭の中に「???」が。 前提知識を持ってないので、何が何やら。

_原子放射線の影響に関する国連科学委員会 - Wikipedia には、核実験の停止要求をかわすために設立された組織、という記述もあるけど、Wikipediaだからなあ…。他の解説をあたってみないと、なんとも…。

とりあえず、これから内容を検討して9月以降に正式な発表をする、と書いてあるから、その時出てくる内容を眺めるほうがヨサゲですかね。

それにしても。権威や肩書にめっぽう弱い日本人という民族の性質をしっかり把握した、巧みな手を打ってくるものだなと、いたく感心してしまったり。コレ、発表内容の信憑性とか、もうどーでもよくなっちゃうよな…。仮に、発表内容を精査して、「アレレー? おかしいぞぉー?」と言ってみたところで、世間の皆様は「バカもん! あの国連様が仰っておられるんだぞ。間違ってるわけないだろーが!」と思考停止して怒鳴り散らして議論にならんだろうなと。いやはや、権力を持ってる方々には敵わんな。こういう手を打てるのか。参った参った。てなことを思ってしまったりもして。

何にしても、今から自分達にもできることと言えば、データをコツコツと貯めていって、全体の推移をのんびりと観察していくことしかできないわけで。どんな発表がなされても、やること・やれることは変わらないのだから、まあいいや、という気も。

データさえ残しておけば、そこで何が起きていたのか、後世の人達が検証できる。もし、データが無ければ、「お告げ」が正しかったのか、間違ってたのか、その検証すら不可能になる。「危険だ」と主張する人も、「安全だ」と主張する人も、主張の正しさを科学的に証明するためには、データを集めていくしかない。だから、今後もサボらず集めていきましょうや、としか。

言い方はアレだけど、こういった調査ができるチャンスは滅多にないのだし。せめてモルモットとして人類の科学の発展に多少なりとも寄与しなきゃ、やられ損というか、被ばく損なので、せめてデータだけでも残して、ちょっとは違う形で元を取らないと、てなことを思うわけですけど。

しかし、日本人って、核関連のモルモットになりっぱなしだなあ…。呪われてるんじゃねえの? そういう意味でも、 _原発神社 作ったほうがいいんじゃないかと…。

他に気になる話をメモ。 :

以下のページが興味深かった。

_速報! 国連科学委員会 福島事故最終報告書 「福島はチェルノブイリではない」: 農と島のありんくりん
_国連科学委員会議長の福島第1原発事故の人体に対する影響の見解: 農と島のありんくりん
_国連放射線影響科学委員会(UNSCEAR)ウォルフガング・ワイス委員長の現時点でのコメント: 極東ブログ

  • 去年の2月ぐらいから出ていた話なので、今になって急に出てきた話ではない。
  • 「事故時の測定データが不足してるので、不確定要素はあるよ?」との言及もついている。
後者の話を聞いて、なんだか信憑性が増してきたなと。本当に分かってる人は、どこらへんが怪しいのか、ちゃんと言及してくれるので…。分からない部分をさっぱり口にしないで「危険だ」「安全だ」と断言しかしない人はあてにならないけど、分からない部分・不明な部分をわざわざ説明してくれる人は結構あてになる、ような気がしますよ。 *1

*1: もちろんそれを「騙しのテクニック」として活用できちゃう人も居るだろうけど、そこまで上手にやってくれるなら、聞いてる側はまず勝負にならない・歯が立たないので、自分的には全然OKです。

2012/05/29(火) [n年前の日記]

#1 [nitijyou] 自宅サーバ止めてました

雷が鳴っていたので、13:00-16:40の間、自宅サーバを止めてました。申し訳ないです。

今日も天気が荒れるとニュースで流れていたけれど、案の定で、なんというか。

#2 [nitijyou] 体調があまりよくない

昨日から、なんだか息苦しく。また、首も痛くて。とりあえず寝ることに。

2011/05/29() [n年前の日記]

#1 [nitijyou] 台風が来るらしい

原発、どうするんだろ。

2010/05/29() [n年前の日記]

#1 [pc] サンワサプライ SKB-WL12BK がまたまた無反応になった

またですよ。条件が分からない…。

日記を検索してみた。

_2010/01/05に購入。
_2010/01/07、無反応に。
_2010/01/15、無反応に。
_2010/04/24、無反応に。
2010/05/29にも無反応に。<本日。

購入して5ヶ月の間に、少なくとも4回ほど無反応になってる・接続が切れる不具合が発生してる。いや、もしかすると、面倒臭くて日記に記録してなかったときもあるかもしれない。となるともう少し発生回数は多くなるかも。

もっと頻繁に接続が切れるなら、初期不良品、もしくは故障してると判断できるのだろうけど。数ヶ月にわたって問題なく使えてしまっているときもあるあたりがなんだか困る。こうなると、何かの条件がトリガーになって不具合が起きるのでは、と想像することもできるけど、その条件については皆目見当がつかない。

メーカに「故障してるよ!」と送ってみても、「確認したけど正常に動いてるぞ」と突っ返されるのがオチだろうし。こういう感じの不具合の出方が一番困るなあ。

2009/05/29(金) [n年前の日記]

#1 [neta][jiji] 「臭いモノには蓋をする」的な日本のソレを「日本の文化」として肯定し続けることに違和感を覚えたりして

_Google Earthの古地図と部落差別問題、本家/.で話題に - スラッシュドット・ジャパン

_「グーグル・アース」に差別地名 国会で指摘され引っ込める - Infoseek ニュース
「ストリートビュー」や書籍の著作権問題などで波紋を広げるグーグルだが、今度は衛星画像表示ソフト「グーグル・アース」の機能に問題が指摘されている。このソフトでは、衛星写真の上に古地図を重ねる機能がある。江戸時代の古地図には差別的な地名が表示されているものがあり、国会でも「差別的に扱われる可能性がある」と質問が出た。

「グーグル・アース」に差別地名 国会で指摘され引っ込める - Infoseek ニュース より

09年3月17日の参院法務委員会で民主党の松岡徹議員(比例代表)が、古地図に「穢多(えた)村」との地名が記載されていることを指摘したのだ。「穢多」とは、かつての被差別階層を指す蔑称で、現代では、通常は公には登場することのない言葉だ。

松岡議員は、

「例えば古地図にあります穢多村、被差別部落、今のところね、出ています。東京では被差別部落は行政的に『ここがそうだ』というふうに地区指定していませんですから、なかなか分かりにくいんですね。しかし、古地図と合わすと分かってきているんですね」

と、古地図から、かつて被差別部落だった場所が特定されてしまうおそれを指摘。「部落解放同盟中央書記長」という肩書きも持っている松岡議員は、さらに

「グーグルがどういう意図でこのサービスを始めたのか分からないが、この状態は、人権侵害につながるのではないか」
「例えば第二の(被差別部落の場所を記した)地名総鑑のように差別的に扱われる可能性がある」

などと訴えた。

「グーグル・アース」に差別地名 国会で指摘され引っ込める - Infoseek ニュース より

グーグル社の手法や姿勢をめぐっては、批判の声もあがっている。ITや企業のコンプライアンス(法令遵守)に詳しい牧野二郎弁護士は、「ストリートビュー」の問題にみられるような「ファクト(事実関係)偏重型」のグーグルの体質を指摘する。

「数百年も前の地図なので、すでに著作権は消滅しています。従って、掲載すること自体に著作権法の問題はありません。グーグルは『事実なんだから、みんなが見られるのは良いことなんだ』という姿勢で一貫しています。地名を語るということは文化・歴史を語ることに他ならないのですが、グーグルはファクトとカルチャー(文化)を混同している。文化的な文脈を無視しています。『ストリートビュー』の時と同じで、国や地域文化や習慣に対する尊敬が足らないのではないでしょうか」

「グーグル・アース」に差別地名 国会で指摘され引っ込める - Infoseek ニュース より


個人的には、「臭いモノには蓋をする」的な日本のソレを、胸を張って「これが日本の文化です。習慣なんです」と他国の人に伝えてしまうことに、恥ずかしさを感じてしまったり。そのへん肯定し続ける日本人であってはいけないのではないか。虚勢でもいいから「そんなものは日本にはありません。ないはずなんです」と言えているほうがまだマシな状態なのでは。と思ったけど日本はそういう問題を今尚抱えているダメダメな国なのです、と明らかにしておくこと自体ある種オープン志向・「隠してない」状態だからそれはそれでいいことなのかなあ、と気がついて、考え込んでしまったり。「隠す」ことを善としてしまう民族であることを「隠さない」民族。なんだかよくわかりませんが。

「穢多」という言葉を隠せば、それで差別はなくなるのだろうか。例えばの話、道路に猫の死骸があったとして、黒いゴミ袋を被せれば、猫の死骸はこの世に存在していないことになるのだろうか。一見死骸が見えなくても悪臭は相変わらず漂うと思うのだけど。それと似たようなもので、言葉を隠せば、古地図を隠せば、差別問題は無くなるのだろうかと。何か対応を間違えてるような気もする。気もするのだけど、じゃあどうすりゃいいのよと問われたら悩んでしまう気もする。

差別用語っぽい部分が含まれることで、差別云々とは全然関係ない部分まで全部公開できなくなるという状況が釈然としない、のかもしれない。>自分。古地図を手軽に閲覧できる利便性や資料性云々と、差別云々を天秤にかけた際、どちらが優先されるべきなのだろうか。

「オタク」という単語を差別的文脈で使ってる人が少なからず居る現代の世の中なわけだけど、差別的文脈で使われることもある単語だから「オタク」という単語をこの世から抹殺しよう、ついでに言えば「オタク」は「ゲーム」「アニメ」等の単語と組み合わせて使うことが多いから、「ゲーム」「アニメ」という単語もこの際抹殺しよう、と言い出す人が居たらどうなるんだろう。件の古地図の問題は、そういう乱暴さを孕んでるような気がしたりしなかったり。

#2 [pc] メインPCのビデオカードドライバを入れ替えたり

GeForce 9500GT用のドライバを、現状の公式版、185.85に変更。相変わらず、スタートメニュー内のメニュー項目がフラッシュして消えてしまう症状が。コレはドライバに起因する不具合ではなくて、別の部分に起因してるのだろうか。よくわからない。

NVIDIAのdemoもいくつか動かしてみたり。 :

  • nalu
  • Luna
  • Mad Mod Mike
  • Adrianne
  • Dawn
  • Squid
  • あたりをDLして動かして、衝撃を受けてしまったりして。こんな映像がリアルタイムで生成可能な時代になってるのか。いや、フレームレートは低いけど。滑らかに動かすにはどれだけのスペックが必要なのやら。恐ろしい。

    ついでに GL Excess を動かしてみたけど、ヌルヌル動いて感動。昔はグググッと重くなるシーンがちょこちょこあったなあ、それが今では、みたいな。

    全然関係ないけど、Mad Mod Mike を見ていて、実は背中にロケットを背負ったキャラって本来人気があるのだろうかと。そういやロケッティアとかあったっけ。アメリカのソレの始祖はそのへんなのだろうか。

2008/05/29(木) [n年前の日記]

#1 [prog] PODってなんぞや

Perlスクリプトを書こうとしてアレコレ検索していたら、 _Getopt::Long - cooldaemonの備忘録 というページで、「=head1 SYNOPSIS」なる行を見かけてなんだろうと。

_Plain Old Documentation - Wikipedia :

Perlスクリプト中にドキュメントを書けるのか! 知らなかった。<オイ。

#2 [iappli] 風景写真を探したりGoogleEarthで空から眺めたり

blender でテスト用地形データを作成していたのだけど。地形データを眺めているうちに、やはりテクスチャを張らないといかんかなという気分に。色を指定しただけのポリゴンではあまりにストイック過ぎる…。というか、どうもそういう地形・風景に見えない。そもそも、現実のソレとは色が違う予感。

それらしい地形の風景写真を、ネットで検索。テクスチャ作成の参考にしようかと。ひたすら検索。ひたすら保存。保存した後でビューアで閲覧。

Google Earth で衛星 or 航空写真も眺めてみる。日本だけではなくて、アメリカも対象にして探す。…色んな形があるなあ。かなり参考になりそう。

もちろん、そのまま使えるわけもないわけで。あくまで参考に、ということで。

別の作り方のほうがいいのかな。 :

ポリゴンで輪郭をとって地形データを作ってみているわけだけど。どうしてもガクガクした輪郭になってしまう。うーん。まあ、いかにもポリゴンで描いてる、という感じがして、かえっていいのかもしれんけど。

テクスチャ主体にしたほうがいいのかな。例えば、256x256 8bitのbmpを複数枚、アプリ動作時に中で作って、正方形上のポリゴンをSubdivide(分割)して割り当てて、とか。中でbmpを作ることにすれば、BG画像をセルで分割するのと同様に、元となるセル画像は少量にすることができるかもしれない = アプリ容量は少なくすることができるかもしれない。が、そもそもbmpを複数枚持つ事なんてできるのだろうか。また、テクスチャを張り付けた際に、輪郭にドットがドーンと見えてしまって、かえって不自然に見えるかもしれず。うーん。

2007/05/29(火) [n年前の日記]

#1 [firefox] _tweetbarのミニアイコンがでない

_tweetbarのアイコンを表示させる
_mike demers dot net >> tweetbar

C:\Documents and Settings\{(username)}\Application Data\Mozilla\Firefox\Profiles\{(xxxxx)}.default\extensions\{(dir)}\chrome\ skin\toolbar-button.css

-  list-style-image: url("chrome://tweetbar/skin/twitter_icon.png");
+  list-style-image: url("chrome://tweetbar/skin/twitter-icon.png");
メモ。

#2 [firefox] Firefox のツールバーカスタマイズが上手くいかなくなる問題

どうも原因が判らん…。拡張を1つ1つ、順にインストールしていったところ、セカンドサーチを入れたタイミングで問題が発生したように思えた。のだけど。その後、セカンドサーチをアンインストール→再インストールしたら、今度は問題が出てこない。うーん。ちなみに、素の profile を作って、セカンドサーチとその他の拡張を入れてみたけど、問題は出なかった。うーん。どういうことだらう。

とりあえず、今のところ構成は下のような感じ。
最終更新時刻: Tue May 29 2007 22:10:08 GMT+0900
UA名: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3
ビルドID: 2007030919

有効な拡張機能: [37]
- All-in-One Gestures 0.18.0: http://perso.wanadoo.fr/marc.boullet/ext/extensions-en.html
- Configuration Mania 1.08.2007013001: http://members.lycos.co.uk/toolbarpalette/confmania/index_en.html
- CuteMenus - Crystal SVG 1.8.2.1: http://www.cutemenuproject.com/
- DOM Inspector 1.8.1.3: http://www.mozilla.org/projects/inspector/
- Download Statusbar 0.9.4.6: http://downloadstatusbar.mozdev.org/
- DownThemAll! 0.9.9.10: http://www.downthemall.net
- Drag de Go 0.2.5: http://forums.mozillazine.org/viewtopic.php?t=440259
- Firebug 1.05: http://www.getfirebug.com/
- FlashTracer 1.3.1: http://www.sephiroth.it
- Gmail Notifier 0.6.0: http://www.nexgenmedia.net/extensions/
- Greasemonkey 0.6.9.20070507.0: http://greasemonkey.mozdev.org/
- IE Tab 1.3.3.20070528: http://ietab.mozdev.org/
- iEPGExtension For RD-Style 0.4.0: http://www.tmjp.net/~tomomori/
- Irvine ContextMenu 1.2: http://multi.nadenade.com/leafy/Mozilla/Irvine/
- JavaScript Actions 2.3.0.2007010501: http://openhideaway.net/Firefox/
- Launchy 4.2.0: http://gemal.dk/mozilla/launchy.html?project=launchy
- MR Tech Local Install 5.3.2.3: http://www.mrtech.com/extensions/local_install/
- OpenBook 1.3.4.1: http://www.chuonthis.com/extensions/
- OpenSearchFox 0.0.0.8: http://forum.moztw.org/viewtopic.php?t=16122
- Popup ALT Attribute 1.3.2005092701: http://piro.sakura.ne.jp/xul/_popupalt.html.en
- PrefBar 3.3.4: http://prefbar.mozdev.org/
- Right Encoding 0.2.2: http://heygom.com/extensions/
- Sage 1.3.10: http://sage.mozdev.org
- Save Session 1.3.0.4: http://diary.noasobi.net/
- ScrapBook 1.2.0.8: http://amb.vis.ne.jp/mozilla/scrapbook/
- SearchBox Sync 0.4.2: http://legege.com/mozilla/
- SearchWP 1.0: http://legege.com/mozilla/
- Show Image 0.4.2: http://showimage.mozdev.org/
- Tab Mix Plus 0.3.5.2: http://tmp.garyr.net
- Talkback 2.0.0.3: http://talkback.mozilla.org/
- Text Link 1.3.2006100702: http://piro.sakura.ne.jp/xul/_textlink.html.en
- tweetbar 1.0: http://tweetbar.com/
- Twitter Notifier 0.9: http://www.naan.net/trac/wiki/TwitterNotifier/
- Web Developer 1.1.3: http://chrispederick.com/work/webdeveloper/
- XUL/Migemo [Forked Edition] 0.5.3: http://piro.sakura.ne.jp/xul/xulmigemo/
- セカンドサーチ 0.3.2007052402: http://piro.sakura.ne.jp/xul/_secondsearch.html.en
- 翻訳パネル 1.4.14.5: http://nazodane.hp.infoseek.co.jp/index.xhtml

無効な拡張機能: [1]
- Java Console 6.0.01: http://www.google.com/search?q=Firefox%20Java%20Console

拡張機能の合計: 38

インストールテーマ: [1]
- Firefox (default): http://www.mozilla.org/

インストールプラグイン: (15)
- DivX Player Netscape Plugin
- DivXR Content Upload Plugin
- DivXR Web Player
- IE Tab Plug-in
- Java(TM) Platform SE 6 U1
- Microsoft Office 2003
- MicrosoftR DRM
- Mozilla Default Plug-in
- QuickTime Plug-in 7.1.6
- RealJukebox NS Plugin
- RealPlayer Version Plugin
- RealPlayer(tm) G2 LiveConnect-Enabled Plug-In (32-bit) 
- Shockwave Flash
- Shockwave for Director
- Windows Media Player Plug-in Dynamic Link Library
何かの拍子にどこかの拡張がコンフリクトするのかしら。たぶん。

#3 [nitijyou] ktからトップページに検索サービスを追加してくれという要望が

とある企業がそっち系の検索サービスをやってるらしいのだけど、それを利用できるように申し込んだらしい。

検索欄のサイズが縦型になってる…。どういうレイアウトにして組み込んだらいいのやら。とりあえず、サイト更新情報の横に float 指定して入れてみたり。メールで更新したことを知らせたけど、たぶん、レイアウトの修正要求が来そうな予感。

#4 [anime][comic][neta] 目の大きい萌えキャラデザインがウケるのは女性の胸を連想させるから

という電波が。構成パーツのバランス的にクリソツな感が。考えてみれば、目の大きいキャラデザはえてして巨乳であり、目の小さいキャラデザはえてして貧乳の場合がほとんど。うむ。矛盾していない。<何がだ。

図を描いて更なる確証を世界中に突きつけようかと思ったがそこまで力を入れるネタでもない気がしてきたのでやめた。

というか。誰かがどこかで書いてた・言ってたネタのような気もしてきた。

この記事へのツッコミ

Re: 目の大きい萌えキャラデザインがウケるのは女性の胸を連想させるから by S    2007/05/30 13:29
ネタですよー。
目の大きい画家っていうと、竹久夢二がいたけど、女性にとても人気だった。
当時の女性が目が大きく巨乳を連想して夢二の挿絵を買ったとは思えないよ。
竹久夢二の代表作がわからない… by mieki256    2007/06/05 01:03
> 目の大きい画家っていうと、竹久夢二がいたけど

気になって画像検索してみたんですが、
目の小さい絵しか出てきませんでした…。
昔はコレで大きいといわれてたのか、
それとも他に目の大きい絵があるのか…。

それはさておき、女性の場合は…
少女漫画等における男性キャラの鼻の高さ・鋭さのあたりが
ポイントなのかもしれないとふと思いました。
つまり鼻の高さは男性の(以下自粛。

もちろんネタでありますが。

2006/05/29(月) [n年前の日記]

#1 [iappli] もう一本を編集中

自機とスクロールの仕様がガラリと変わったのでそのへん修正。

敵が発生しなくなってしまった。地形objも敵として発生させてたので先に進めない。ついでだから敵発生テーブルを参照して発生させるように。…その前に敵発生テーブルを作成しないと。

マップエディタで配置して、それを座標値テーブルに変換するPerlスクリプトを作成。

#2 [pc] 液晶ディスプレイについて少し調べたり

もはや15型や17型は市場として終わってるというか末期なのね…。パネルの種類に関してほとんど選択肢がない。19型以上の製品群が主流になりつつあるらしい。

_パーツの基礎知識 > ディスプレイ(2) :

15型や17型の製品について調べたらほとんどの製品が擬似フルカラーでちとショックを受けたり。 :

1619万色、あるいは1620万色とスペック表に書いてあるものは擬似フルカラー *1 で、1677万色と書いてあるものが一応フルカラー表示、らしい。

*1: ディザ、もしくは点滅で、パネルの性能上、表示できない色を誤魔化して(?)表示するらしい。

#3 [pc] _TEC V-mouse VM-101BL - ペン型マウス

ペン型のマウスを使うぐらいならタブレットを使ったほうがいいのでは。と思っていたのだけど。解像度が極めて高い故に、膝(?)の上でスイスイと動かせるというのはなんだか魅力的。肩・肘・手首が疲れずにすみそうな予感。これは結構ヨサゲかも…。

や。親父さんが「腕が痛い」「腕が痛い」としょっちゅうこぼしてるので。どうもマウスの位置が高いというか、マウスまでの距離がありすぎるらしく。ということでこういう製品が気になるわけで。

なんていうか…。もっと手をだらんとさせた状態で使えるポインティングデバイスはないものだろうか。

#4 [pc] _一眼レフデジカメユーザーに最適! 安価なカラーキャリブレーションキット「Huey」が発売に!

_自動モニタ最適化ツール「huey」

15,000円でキャリブレーションができるというのは魅力的かもしれず。

#5 [linux] 自宅サーバのSAMBAがエラーを出してるっぽい

smbd が /var/log/message にエラーを残してるっぽくて。
May 29 22:50:57 kerochan smbd[5105]: [2006/05/29 22:50:57.496434, 0] lib/util_sock.c:get_peer_addr(1000)
May 29 22:50:57 kerochan smbd[5105]:   getpeername failed. Error was 転送先が接続されていません
May 29 22:50:57 kerochan smbd[5105]: [2006/05/29 22:50:57.501904, 0] lib/util_sock.c:get_peer_addr(1000)
May 29 22:50:57 kerochan smbd[5105]:   getpeername failed. Error was 転送先が接続されていません
May 29 22:50:57 kerochan smbd[5105]: [2006/05/29 22:50:57.502200, 0] lib/access.c:check_access(328)
May 29 22:50:57 kerochan smbd[5105]: [2006/05/29 22:50:57.502311, 0] lib/util_sock.c:get_peer_addr(1000)
May 29 22:50:57 kerochan smbd[5105]:   getpeername failed. Error was 転送先が接続されていません
May 29 22:50:57 kerochan smbd[5105]:   Denied connection from  (0.0.0.0)
May 29 22:50:57 kerochan smbd[5105]: [2006/05/29 22:50:57.502652, 0] lib/util_sock.c:get_peer_addr(1000)
May 29 22:50:57 kerochan smbd[5105]:   getpeername failed. Error was 転送先が接続されていません
May 29 22:50:57 kerochan smbd[5105]:   Connection denied from 0.0.0.0
May 29 22:50:57 kerochan smbd[5105]: [2006/05/29 22:50:57.502958, 0] lib/util_sock.c:write_socket_data(430)
May 29 22:50:57 kerochan smbd[5105]:   write_socket_data: write failure. Error = 接続が他からリセットされました
May 29 22:50:57 kerochan smbd[5105]: [2006/05/29 22:50:57.509801, 0] lib/util_sock.c:write_socket(455)
May 29 22:50:57 kerochan smbd[5105]:   write_socket: Error writing 5 bytes to socket 5: ERRNO = 接続が他からリセットされました
May 29 22:50:57 kerochan smbd[5105]: [2006/05/29 22:50:57.517036, 0] lib/util_sock.c:send_smb(647)
May 29 22:50:57 kerochan smbd[5105]:   Error writing 5 bytes to client. -1. (接続が他からリセットされました)
関連情報について検索してみたけど。クライアント側でメッセンジャーサービスが動いてないから、という話を見かけた。

WinXP 上で、管理ツール → サービス、から、「Messenger」を開始してみた。自分のPCだけではアレなので、親父さんのPCも同様に設定。してみたけど変化なし。すると、このエラーはメッセンジャーサービス云々と関係ないということだろうか。

smb.conf の記述にマズイところがあるのだろうか。と思って、よくわからんけど「interfaces = 192.168.1.0/24, 127.0.0.1」とか「dns proxy = No」とか指定。してみたけど変化なし。

/etc/samba/lmhosts の内容が昔の状態になってたので修正。してみたけど変化なし。

あかんわ。基礎から勉強する必要がありそうな予感。

2005/05/29() [n年前の日記]

#1 [nitijyou][pc] 親父さん用マウス、その後

親父さんとマウスについて話をしてるうちに。以前弟が置いてった、logicool製ボール式無線マウスを試しに使ってみる、という流れに。

ただ、このマウス、元々親父さん用に弟が置いていったのだけど、何かしらの理由で親父さんが気に入らなくて放置してた記憶が…。何が気に入らなかったのか、自分も、親父さんも、覚えてないんだよなぁ…。それと、ボール式なのがちと不安。親父さんのマウス利用スペースはとにかく汚れているので。 *1

マウスの型番が判らん :

関連ソフトが欲しいのだけど、古いマウスな上に、たしかボタンを自力で修理した云々で裏面のシールが切り取られていて、型番が判らん…。メーカサイトにも既に情報が一切載ってないし。…logicoolだかlogtechだかは、生産終了・販売終了製品の情報公開の姿勢にちょっと問題があると思います。が、それはとりあえず置いといて。logicoolのサイトから、MouseWare 9.79.1 build 25 とやらをDL。インストールしてもらった。一応動いてはいるみたい。や。入れなくても一応動いてたけど。念のためというか。

型番が判らないのは気になるので、あちこち検索してみた。おそらくそれっぽいのは、CM-41PR か、 _CM-61H か…。 _CM-61Hと受信機形状は同じ だけど…。

_二つを並べてる写真があった。 CM-41PR のほうは、受信機にLEDがない。ということは、CM-61H だな。発売時期は… _1998/07/25。 古い。何年前じゃ。逆に言うと、これだけ年数が経過してるのだから、今現在、店頭で販売されてるこの手のマウスは、よほど進化してるのだろうな。…といっても光学式になったことと、よくて電力消費が改善したぐらい、なのかな。後は、有名デザイナーを連れてきて云々、とか。あ。横スクロールもできるようになってるのか。…って、横スクロールはたいした進化じゃないような。だって、昔からA4techじゃ横スクロールぐらい日常茶飯事だぜ!

*1: 以前、親父さんがボール式マウスを利用してた頃、作業のために親父さんPCに触ったら、マウスの動きがめちゃ悪い=ボールが汚れまくりで驚いたぐらいで。

#2 [zatta] 「ロスじゃ〜日常茶飯事だぜ!」の元ネタって何でせうか

_「「ロスじゃ〜日常茶飯事だ」って金田一の明智さんのセリフだったんだ知らなんだ」 とある。金田一? 明智? _「明智小五郎VS金田一耕助」 のことかしら。なんかイメージが合わない。

_『金田一少年の事件簿』 のほうか。明智警視なるキャラが出てるみたいだし。少年漫画は全く読まないから判らなかった。

_『「雪夜叉伝説殺人事件」で初登場した明智警視、その時たびたび言っていた「ロスでは…」の真実が明かされます。』 とあるから、そうなんだろう。

いや。なんとなくだけど、更に元ネタがありそうな気もする。米映画・米のドラマなんかで耳にしそうな言い方だし。が、そこまでは見つからず。なんかこのままだと、『金田一少年の事件簿』がオリジナル、ということになりそうだなぁ。

さておき。「ロスじゃ」「ロスでは」「ロスじゃあ」とか、色々あるみたいだな…。

#3 [prog] _Web Matrixで始めるWebアプリ・プログラミング 第1回 オール・フリーなASP.NET統合開発環境

ちょっと気になったのでメモ。

開発中は独自Webサーバを利用して動作確認できるらしいけど…。Webサーバ、というかIIS上でしか動かせない云々はなんだか厳しいなぁ。それとも、Linux上でも動かせるのかしら。

#4 [windows] エクスプローラの右クリックメニュー → 送る、からファイル名やパスをコピーしたいのだけど

ヨサゲなツールはないかしら。

_右クリックメニューの[送る]にさまざまなツールを登録できる「"SendTo" Toys」 :

インストールしてみた。通常、フルパスでコピーされるけど。該当項目にチェックを入れれば、ファイル名 or フォルダ名だけコピーもできるらしい。改行コード変換やMD5出力もあるらしいので、なかなかイイ感じかも。

できれば、「フルパスのコピー」「ファイル名のコピー」を、メニューの時点で分けたいのだけど…。ショートカットファイルをコピーして、渡すオプションを変えて云々では対応できないかしら。

_ArtTipsの機能説明 -moewe- :

ランチャーとして使ってるのだけど。う。sendto にショートカットを入れとけば、フルパスも、ファイル名も取得できたのか。 *1 知らなかった…。コレを使えばよかったのか…。

*1: 左クリックでフルパスをコピー。右クリックでファイル名 or フォルダ名をコピー。

#5 [windows] HDD内の容量とDVD-Rに記録できる容量との関係がわからない

「あふ」でフォルダサイズを表示しながら、「ここまではDVD-Rに入るかな」とファイル・フォルダをまとめた後で、Nero Express でファイル・フォルダを追加すると…まだまだ容量的に余裕があったりする場面が結構あったり。うーむ。それぞれがどういう計算をしてるのかがわからん…。

エクスプローラ上で、フォルダのプロパティを表示してみると :

「サイズ」と「ディスク上のサイズ」の2つがあった。「あふ」で表示してるのは後者で、Nero Express が表示してるのは前者らしい。「あふ」が扱うのは、主にHDD上のファイルなわけで…HDD上のサイズで扱わないと、問題がありそうなわけで、これはこれで。

あ! 今まで、「あふ」で「I」を使って容量表示をしてたけど。「Shift + I」で、単純合計容量を表示してくれる。知らなかった…。コレを使えばよかったのか…。<またかよ…。

DVD-Rにはどのくらい入るのかな :

Nero Express で、ディスク情報を表示すると、「4489MB」と表示される。

_MPEG-2,DVDビデオ,MPEG-1,ビデオCDのファイルサイズの計算方法とディスク容量 というページに、DVD=4488MBという記述があるので、たぶんこれが近いんだろう。となると、
4,706,074,624 byte
4,595,776 KB
約4,488 MB
つまり、4,706,074,624 byte 未満でまとめればいいのか。…つーかそれだと覚えにくいから、4,700,000,000 byteで抑えておけばOK、と覚えておけばいいのかもしれず。

残念。甘かった。フォルダサイズを 4,700,000,000 byte 未満にしたものの、Nero Express に追加してみると、容量をオーバーしてしまう。何故。

クラスタの差異、かしら。フォルダが入ってるHDDパーティションは、FAT32、1クラスタ16384 byte。DVD-R は…いくつなんだろう。データCDは、1クラスタ 2048 byte らしいけど。とりあえず、そのへんが関係していそうな予感。単純合計容量では収まってるように見えても、クラスタ云々でさらに増える、みたいな。しかしそれが判ったところで、DVD-Rに焼いたときの容量を算出する方法がわからん…。各ファイルのサイズにもよるだろうしなぁ…。

というわけで解決策は見つからず。うーん。

_FAT12、FAT16、FAT32、NTFSのデフォルトクラスターサイズを教えて下さい :

NT3.51 以降では NTFS の標準クラスターサイズは 4KB が上限になります。
たしかに手元のNTFSパーティションは1クラスタ4KBっぽい。

_CDRvsDVDRc - CDRとDVDRの保存容量と値段を比較 :

DVD-R繋がりで。ちょっと気になったのでインストールしてみた。…ってコレ、コマンドラインで動く版だった。 _CDRvsDVDR が、GUI版。なるほど。一々電卓を叩く必要がなくて楽チン。

コレ。さらに、DVD-R/RWドライブの値段も入力させて、「DVD-Rをxx枚焼けば、DVD-R/RWドライブ増設コストの元が取れます」とか表示したら、ドライブ購入を悩んでる人の背中を押せるかもしれず。<って押してどうする。

#6 [anime] _「DVDが売れない」という話

_(via 読書記録ChangeLog)

#7 [web][jiji][neta] 価格コムはIT業界のJR西日本

という一文がふと脳裏に。つーか「○○は○○業界のJR西日本」って喩え(?)は色々使えそうだなと思ったのでメモ。と思ったけど今しか使えないというか、どこにも使い道がないというか。

なんで急にそんなことを思い浮かべたかと言うと :

午前中、TVをつけてたら、例の脱線事故の特集が流れてて。それを見てるうちになんとなく。

都合のいいように編集されてるのかもしれんけど。それでも、無知な自分には勉強になる特集だった。
  • 既に装備されてたATS-Pでも使い方によっては充分に事故は防げた。
  • そういうATS-Pの使い方をJR西日本も知っていたし、そのような運用をしてる場所も実際にあるが、「独自の判断」による設置基準・規定があった故に、件の事故現場には対策されてなかった。
  • 本来ATS-Pの設置基準には「速度差」が関わってくるのに、JR西日本が「最高速度」で「規定」を作ってるあたりが謎。JR西日本は、この手の技術に対して理解できてない?
  • 元々予定していたと主張するATS-SW導入計画は本当に存在してるのかなんだか怪しい。
  • ATS-SW導入の計画関連文書を見せてもらえないか、と要求する記者に対し、社内資料だからダメの一点張りの姿が、ますます怪しさを倍増。
  • 私鉄が、件の事故の後、ATS-Pをさらに活用・対策を打っているが、自主的に対策を打たず、「国土交通省が設置基準を出してくるのを待ってる」と言い続けるJR西日本の姿がなんというか。
という感じで、なんか色々とアレだなと思ったり。 *1

*1: まあ、一番最後のはアレだけど…。私鉄より場所が広いからコストがかかるだろうし。少しでもダイヤをアレにしたいだろうし。故に余計なことはしたくないんだろうけど。そのへんの事情は判るような気もする。かといって肯定できることではないとも思うけど。でも、駅員を線路に突き落とす、そんな利用客が居るようなヤバイ地域だしなぁ…。「安全にしました」「その代わり時間がかかります」なんて言ったら、利用客から何されるかわからんのかも。嘘。

#8 [pc] _プレゼンで使えるアイコン集

おお。コンピュータ関連機材のアイコンがたくさん。ヨサゲ。 _(via TokuLog!)

#9 [anime] ケロロ軍曹、サードチルドレン顔見せの回

ガンダムは出てくるわ、ガンプラ三昧だわ、掃除機やブラシに角がついてるわ。素晴らしい。でも、なんとなく、何かチクチク責められてるような…。被害妄想かしら。

#10 [anime] ネクサス、解説の回

上司の人が悲しいお父さんぶりを披露。悪者かと思ってたけど、こういうシーンを入れられちゃうと…。1stガンダムのドズル・ザビみたい。違うか。

映画版とのリンクを解説。アメリカ側の写真がそれっぽくてイイ感じ。CGレタッチ万歳。

市街地に怪獣が。…ダメだ! そんなところで戦ったら制作費が! <オイ。

#11 [anime] ジャスティライザー、親切な大ボスの回

どこでロケをしてるんだろう。なんだか湖っぽいけど…。それとも合成なんだろうか。

シン様とお姫様の間に、もう少し何かが欲しい気も。現状ではシン様があまりに冷たすぎる。感情を抑える必然性を感じさせる・悲恋になりそうな予兆を感じさせる外的圧力とか。そういうのを盛り込めないかしら。でもまあ、そこまで盛り込むとややこしくなるかな。

部下が居なくなったので、大ボス自ら、作戦を『独り言』で解説。親切だけど、なんだか哀愁も感じる。

「私を倒してから行きなさい」に笑ってしまった。なんでそうなるの。先日見たBJの回などとは正反対かも。登場人物のその場のノリ・感情のみで、脈絡なく話が進んでいく…。違う意味で、これはこれでスゴイ。

メカゴジラが大変なことに。ビックリ。この“いきなり”にはやられた。金属で出来たロボットが、まさかそうなるとは。完全に予想外。

『チーン』に笑った。さては鹿島監督、浦沢脚本で開眼してしまったのでは。…それとも元々そういう作風なのかしら。

延々とワイヤーアクションで戦い続ける赤の人と紺の人。頑張るなぁ。仕上がりは別にして、あまりに軽々と飛び回るので、なんだか人形劇を見てるような感覚に。人を操ってるように見えない。

愛する人が敵に拉致されたというのに、赤の人とにこやかに談笑する黒の人。もう何がなんだか(笑)

#12 [anime] _『笑う大天使(ミカエル)』映画化決定

ジャスティライザーの感想blogを眺めていて、知った。なんとまあ。原作、読んだことがあるはずだけど、覚えてないや… <オイ。

ジャスティライザー29話、30話のアクション監督を務めた方が、『笑う大天使』のアクション監督もやっているらしい。 _仕事一覧情報 を眺めたけど、いやはや、なんとも精力的な仕事ぶり。凄すぎる。 *1

件の方の公式サイトの日記が見れなくてアレだったけど、 _Googleキャッシュに残ってた。 「編集はほぼ終わり」「膨大なCG作業が残ってる」「ラストのアクション全部グリーンバック」「完成は年末くらい」…。なんだか『CASSHERN』を思い浮かべてしまった。全体的に、そういう感じになってきてるのだろうなぁ…。もう、CG無しの映画制作は考えにくい、とか。
*1: ジャスティライザーの29話って、剣を交換する回かしら。もしかするとこの方の発案なのかな。30話は…。スイマセン。うさぎ跳びがずーっと気になってしまって、全然チェックしてませんでした。

#13 [anime] エウレカセブン、出前の回

アハハハ。なんだこのアニメ。妙。…でも、考えさせられてしまった。上手いなぁ。

#14 [anime] マジレンジャー、鍵の人の回

言葉を喋れないキャラって、なんか新鮮…。アニメならよくあるけど、特撮じゃ珍しい感も。でもないか。それはともかく、結構なお歳のお姉さんに見える…。もしかして、お姉さんが若い男の子を、ってところがセールスポイントなんだろうか。<なんじゃそりゃ。

雲の上を魔法のほうきで飛ぶ、赤の人とお姉さん。特撮万歳。

敵のヴァンパイアの片方。前から思ってたんだけど、実は結構演技が上手いような気がする。密かに注目。

#15 [anime] ライダーヒビキ、挫けぬ回

カスミ姉さんに怪我の手当てをしてもらうなんて…。イブキくん、よかったねぇ。

ヒビキおじさん…。やっぱりそうなんだ…。少年とは逆で、相手のほうが鈍いのか、な?

イブキくんと弟子のやりとり。テキパキした感じがなかなか。上手いな。

出陣するイブキくん。株が急騰。これまた火打石がグー。ここでその小道具に意味を重ねるとは。あまりに鮮やかな見せ方に、思わずため息。

あら。このロケ場所は。555の…。

いいラストだなぁ。でも、まさかこれでパターン化?

VFXアーチストの人数。凄いよなぁ。なんだかアニメみたい(?)。

次回、ギター侍の活躍かしら。楽しみナリ。「俺の歌を聴けー!」ですな。って作品違いますからー! 残念! とか。…ギターが出てくると色々絡めることができるから、いいな。<何がだ。

#16 [anime] プリキュアmax、研究発表の回

敵の弁慶みたいなの。いいなぁ。唐突で、いい。

白の人も唐突だな。や、でも、解決に至る道は、なんかいい感じ。それを思い出して元に戻れるなら、当人にとって、それが一番いい。

新しい玩具、登場。これまた唐突だなぁ。

Bパート。白の人の言を聞いて、唐突さは消えた。が、ハラハラしてしまった。いいのだろうか。この番組でそんなこと言っていいのだろうか。去年と同じテーマでグランプリをとることを周囲から望まれてるのだろうに…。いや、もしかすると、スタッフの所信表明でもあるのかしら。ってそこまで考えなくてもいいか。

まさか新玩具をそんな形で活用するとは。てっきり、チラリと見せて終わりかと思ってた。やられた。

なんて酷いラストだ…。貴重なメガネそばかすっ娘キャラを、レギュラー陣全員が笑うの図は、我輩納得がいかん! メガネそばかすっ娘は保護せよ! <オイ。や。白の人の失態をカバーすべく力を尽くしてくれたわけでしょ。それを笑う白の人って、いくら幼児向け番組と言ってもあんまりじゃないかと。…まあ、最後は無理にでもオチをつけなきゃいかんという制約でもあるのだろうけど。つーか自分もこの展開でオチなんか思いつかないです。笑って誤魔化すしかないよねぇ。…考えてみたら、ライダーヒビキのラストも笑って誤魔化す系なのかしら。むぅ。

2004/05/29() [n年前の日記]

#1 [zatta] _動き絵

浮世絵アニメ。なんとなく、8bitPC時代(中期)のDEMOプログラムを思い出したり。当時は名画を表示するDEMOがチラホラ見受けられた。8色しか出ないのに。何故。無謀だ。 _(via はてなダイアリー - 風が吹いても誰も儲からない)

#2 [nitijyou] トム・ヤン・クン味の菓子を食べた

CHOUKARAとかいうやつ。眠かったのに、頭のあたりがブワーッと。うーむ、激辛スナックって凄いのだな。

その後、寝込みました。喉も痛い。うう。

2003/05/29(木) [n年前の日記]

#1 _こないだの地震は巨大地震の前触れの可能性大という話

があるらしいので気をつけないと。

ヘルメットをかぶった萌えキャラ「地震対策タン」 :

を作って地震対策に関する啓蒙活動ができないものかと思ってみたり。ビスケタンみたいな感じのデザインで。 *1

*1: ていうかビスケタンって何?

この記事へのツッコミ

Re: 巨大地震の前触れの可能性という話 by がんした    2003/06/01 06:29
結局、地震てば予知出来ないから、直前まで日常生活しつづけないと仕方ないし。
生きるとか死ぬなんて、殆ど運だもんな。
Re: 巨大地震の前触れの可能性という話 by mieki256    2003/06/02 01:17
日常生活でも使えて、かつ避難生活・緊急時でも使える
食材・機材がもっとたくさんあれば、
いざという時も困らないんでしょうけどね。
せいぜいカップラーメンぐらいしか思いつかないなぁ…
乾パンは、ちょっとやだ。美味しくないし。

あとはケータイですか。アレはどちらの時も役に立つ。
大元のシステムがダウンしていなければ、ですが…
ていうか自分ケータイ持ってないか。ダメじゃん(爆)
Re: 巨大地震の前触れの可能性という話 by がんした    2003/06/02 07:55
こっちの自治体でも東海大震災を想定して、いろいろとシュミレートや訓練してます。
陸路から近づけない想定で、海上自衛隊の「おおすみ」に消防車や警察車両とか
満載してホバークラフトで浜辺から上陸してみたり。
http://www.10d.mae.jgsdf.go.jp/photo/p12.htm

災害後の救助作業は、阪神淡路大震災とかこの間の東海豪雨とかの
教訓から綿密に計画されてるが、災害前の対応が苦労してるみたい。
最初、注意勧告の時点で交通公共機関を全面ストップしようとしたが、
そんな事したら未帰宅者が大量発生して大変だとかで、
避難勧告が出るまで、原則として運転するようにしたとか。

なかなか、注意警報出てから地震が来るまで、自宅に籠もってる訳にもいかないもんね。
Re: 巨大地震の前触れの可能性という話 by mieki256    2003/06/02 23:45
うわ! ホバークラフト…カッコイイ! 燃える!
いや、何の為に訓練してるかを考えると不謹慎しかもしれないけど。
でもカッコイイ、その写真…

注意勧告と避難勧告の違いが気になったので検索してみたけれど
具体的にこのように違うと書いてあるページが見つかりませんでしたわ。
まあ、注意<避難、なのだろうけど…

検索中、警視庁のサイトで地震対策のページを見つけたり。
地震による災害時は、やっぱり警察が大活躍するのかな。
http://www.keishicho.metro.tokyo.jp/seian/jisin/jisin.htm

自分の住んでる須賀川市のサイトに、地震が起きた時の行動なり対策についての
情報が載ってるかなと思って探してみたけど、どうも載ってないみたい。
pdfでもいいから載せておいて欲しいものだけど…
この感じからすると、たぶん対策とかあまり考えて無さそうな気がする。
http://www.city.sukagawa.fukushima.jp/
Re: 巨大地震の前触れの可能性という話 by がんした    2003/06/03 08:20
注意とか警報とかココに載ってましたが、意味がさーぱり。
http://www.city.nagoya.jp/60syobou/zisin_kyouka/kyouka_gaiyou.htm

天災は内戦とか戦争と違って、相手が自然だから被害が出ても後腐れないし
救助者には素直に「ありがとう」と言えるので、どうしても気が楽だよ。
気分はサンダーバートだし。

警察や自衛隊より消防が最前線になるのだろう。その為の装備も日々増強されてるし。
http://www2.neweb.ne.jp/wc/ebara71/a/hr/tc1.htm
http://www2.neweb.ne.jp/wc/ebara71/a/b/p2.htm
http://www2.neweb.ne.jp/wc/ebara71/a/hr/tw.htm
http://www.city.ichikawa.chiba.jp/net/fire/syaryou/tokukyuu.htm
http://www2.neweb.ne.jp/wc/ebara71/a/rob.htm
Re: 巨大地震の前触れの可能性という話 by mieki256    2003/06/03 23:28
上記文書は、おそらく、お役所内部向けの文書なのでしょうけど…
これ、役所の人達も理解できるんだろうか。
実行する人達が理解できない文書の書き方してたらかなーりマズーイ気もする。
そもそも理解・記憶できてなかったら、
いざという時、どこまで実行できるのかも怪しいんとちゃうかなぁ…

後者の写真、カラーリングが良いですな。
通常の3倍のパワーで瓦礫をどけたり、
通常の3倍の速度で現場に急行できそうなイメージが… ( ̄ー ̄)ニヤリ
Re: 巨大地震の前触れの可能性という話 by がんした    2003/06/04 21:34
パイロットが皆、黒いサングラスしてナルシスト。
救助失敗する度に「認めたくないものだな、若さ故の…」と言い訳がましい。
海上保安庁の「白いヤツ」をライバル視するも、最後まで負けつづけ。

                    なんだかなーー ヽ(´∇`)ノ
Re: 巨大地震の前触れの可能性という話 by mieki256    2003/06/05 06:35
>海上保安庁の「白いヤツ」をライバル視
ワラタ
Re: 巨大地震の前触れの可能性という話 by がんした    2003/06/06 06:34
更に、陸自のレスキュー部隊は全員、強化人間。

■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■|Φ(|´|∇|`|)Φ|■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
みえきさん、話ずれるけどココ、両側から攻められて辛いです。
Re: 巨大地震の前触れの可能性という話 by がんした    2003/06/07 08:06
以前より見やすいけど、依然と両側から攻められてるような、、、。
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■|Φ(|´|∇|`|)Φ|■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
上の[ツリー表示]みたいに、左から段落落としていくとか、
まぁ、これで十分と言えばそうだけど。
Re: 巨大地震の前触れの可能性という話 by mieki256    2003/06/08 05:19
こんな感じでどうでせう。左側のスペーシングを無くしただけですが(爆)

なんか上手い方法ないかなー、皆どうやってこのへん解決してるんだろう。
しかしCSS使ったらNN4.xがハングしたのには参った。
いくらなんでもハングはマズ過ぎるよなぁ…
それさえなければCSS使ってそこそこ問題解決だったのに…弱すぎるぞ…NN4.x

#2 _イラク戦争がもたらしたもの

自分も予想が外れたクチ。もっと長引くと思ってた。

#3 [pc][web] _HTMLメールが急増中らしいが

最近のOutlookExpressは、HTMLメールを強制的にテキスト形式で受信してしまうオプションがあるので、オイラなんかはそれをONにしてるのだけど。 *1 返信しようとした際に、初めてHTMLメールが送られてきていた事に気づく事もしばしば。 *2 そういった事を考えると、 HTMLメールを嫌ってる層が減ったのではなく、ソフトウェア的にHTMLメールを「最初から無視」できる状況になった、てな面があったりしないのだろうか。とすれば、今頃HTMLメールで広告メールを送信し始めるってどうなのよ。

配信停止を希望する客はどのみち少ないのでは :

件のページでは「配信停止を希望したユーザは少数」=「HTMLメールが受け入れられてる」としてるけど、実態は違うような気も。配信停止のアクションを起こせば「メールアドレスが生きてる」事を相手に伝えてしまい、ますます広告メールが増えてしまう事例が多い事を、多少知識のあるユーザであれば知ってるわけで。故に通常は配信停止のアクションなんて滅多に起こさないし、わざわざ希望・連絡するのって初心者ぐらいじゃないのか、と。

テーブルを多用して凝ったレイアウトをしてるHTMLメールは困る :

テキスト形式で受信すると解読不可能な状況になる。読めないメール受け取ってもな。捨てるしかない。

たかがAAごときを見せる為に固定ピッチフォントを強要してくるのも困る :

例えば「旅の窓口」の広告メールの冒頭についてるAAとか。ご丁寧にも「固定ピッチフォントで見てください」なんて書いてある。なんであんたらの都合にこっちがわざわざ手間隙かけて合わさねばならんのだ。客の使用するフォント種類を強要・強制・決め打ちできるほどに貴社はお偉い存在なので御座いますかと。それでいて何? あのAA? 2chのAAのほうがよほど面白い。どうでもいいAAを見せる為に固定ピッチフォントを客に強要する…それが企業にとってプラスになると思ってたらアホ過ぎ。 *3

*1: 開いただけでウイルス感染するHTMLメールなんかまともに受信していられないッス。
*2: オイラの環境では、返信時、元がHTMLメールの場合はリッチテキストモード(HTMLメールのモード)になるみたい。
*3: もっともおそらく、件の企業の大半の顧客は女性なのだろうから、むしろプラスに働いてる可能性も否定できないけど。女性ってそういうの無意味に喜びそうだし。だったらいっそHTMLメールにしてJavaScriptやJavaアプレットでマウスカーソルを猫や蝶が追いかけたり花びらが散ったりしたほうが喜ばれるのとちゃうか。

#4 ヤンキーの語源ってなんだろう

ヤングモンキーの略かな。

結構深いのか? :

_「ヤンキー 語源」 でgoogle検索。( _1 _2 _3 _4 ) そうか。アメリカ人の呼称がヤンキーで、米国人の姿形を真似する日本人の若者=ヤンキーと。更にその呼称は周囲から与えられたものではなく内部から自発的に発生していた可能性が高いというあたり興味深い。日本型ヤンキー発生当時の彼等の中では「俺ってばまるでアメリカ人のようにカッコいいんだぜ」的自尊心があったのだろうか。もっとも今では当時の心情や志など全く残ってないだろうし、やはり日本国内で独自の文化に改変されてしまったわけで。アメリカ人を目指してみたはずの日本型ヤンキーが、外国から持ち込んだ文化を自分達向きに大幅にアレンジしてしまうという、いかにもな日本人的展開をしてしまったとなれば若干面白い現象と言えるのかも。

今時「アメリカ人=カッコイイ」もないよな :

グローバル的視点で見ればアメリカ文化なんて憎悪される対象であることのほうが多い時代だし。

大学の構内でヤンキーって見た事無い :

制服が規定されてる環境が存在しないとヤンキーも発生し得ないのだろうか。つまりアレはせいぜい中学〜高校の期間にのみ有効な文化って事なのか。

2002/05/29(水) [n年前の日記]

#1 チクチク

チクチクと入力。
チクチクなのかコチコチなのかチョボチョボなのか…


自鯖で、ftp接続できないという不具合が。
仕組みをガッチリ理解してないんで、原因がどこかわかんない… >自分
LAN内は問題出てないから、ルータから先なのは確実だけど。
そこは手が届かないのでなんとも…
まだルータがログ出してくれればアレだろうな。
ウチのは安物だからそんなの出ないけど。
つくづく、YAMAHAのルータっていい製品だったな。高いけど。

2001/05/29(火) [n年前の日記]

#1 畑の石

珍しく朝食を食べようと階下に降りたのが運の尽き。
親父さんの畑仕事の手伝いをさせられる事に。

サツマイモの苗を植えたんですが。
畑の中の石ころって、むっちゃ作業の邪魔になるんですね。
恥ずかしながら、この歳で初めて認識。

数日前の新聞で見たんですが。

国が数年前、雄国山近辺で農地開拓の計画を立てたそうで。
ところが…
その土地、石だらけでとても農地にならないと
調査の段階で既に判明してたのです。

しかし。さすがは日本の優秀な官僚達。
「その手の計画をガンガン進めないと、自分達の仕事が無くなる」
と無理矢理進めちゃった。

結果、数年経過しても農地は出来ず。只の荒地が残るだけ。
近隣農家は、農地になる見込みも無いのに、
その計画で背負わされた借金を、未だに返し続けねばならず…

…といった記事の内容。

で、思ったんですが。
農業関係を担当する官僚達に、就任と同時に、
強制的にそういう荒地で体験作業をさせてはどうかと。
大変さを体で知れば、そういうアホな事、ちっとは少なくなるんじゃないかと。
「子供達にボランティア作業を強制」より意味があるんじゃないかな。

にしても。
そういうダメダメな税金の使い方しといて、
「国民の皆さんにも痛みを〜」
って説得力無いなぁ。
その前に、もっとやることあるんじゃないか。
言う事聞かせられそうな弱っちいヤツラから、
まずは搾り取ろうという腹ですか。
穴だらけのバケツにいくら水入れても溜まりませんよ…

なんてことを、石ころ除去作業しながらぼんやりと考えてました。
寝てない体にはちょっと日差しが強くて…
バカな考えも浮かんでくるってもんです (;´_`)


帰ってきて爆睡。
気がついたら、「ウェブダイバー」も「ムリョウ」も終わってた。
ビデオ予約、しとけば良かった… (T_T)

2000/05/29(月) [n年前の日記]

#1 index.htmlは見えたけど

昨日の、「public_htmlの中が見れない」の件ですが。
原因はディレクトリィのパーミッション設定でした〜 (´Д`;)トホホ
Linux関連ML過去ログなどを必死に漁ったのですが、ほとんどが原因はそのへんのようで。
ユーザホームディレクトリ、public_htmlに、 chmod o+r 〜とか、chmod o+x 〜を指定して、OK。
ディレクトリィ構成も問題は無く、各ユーザのホームディレクトリの下に、公開すべきディレクトリを作ってしまってOK。
つか、これは、etc/httpd/conf/srm.conf の中で
  UserDir public_html
と指定してあるから「OK」なんだけど。
何はともあれ、ようやく http://Linuxマシンホスト名/~ユーザ名/ で、index.htmlをWinマシンから拝めたのであります。

しかし新たな問題が。
Winマシンから、FTPソフトを使って、Linuxマシン上のユーザホームディレクトリに、htmlやcgiのファイルを送ろうとしたところ、ユーザのホームディレクトリの中が丸見え。ありゃ〜
しかもなぜか肝心のpublic_htmlの中は見えない。
SAMBAを介し(?)ても=Winのネットワークコンピュータ上からも、見えない… > public_htmlの中
…これはいかんよチミぃ。
そこで、いわゆるプロバイダなんかのFTPアップ時のような状態…FTPソフトで接続すると、public_htmlの中にしかアクセスできない、という設定にできないだろうかと調べ始めたのですが。
…なんかとても面倒臭そうなんですけど。
今、一般的に ftpd というと、wu-ftpdが使われてる場合が殆どらしいのでですけど(Vine Linuxのデフォルトもソレ)、それについての情報を探してみたら、なんだか頭がクラクラ。
MLなんかを覗いても、「ftpd と chroot で検索すれ」としかレス(?)がついてなかったり。
う〜ん…
なんか大変な事になってきたような気も。

嫌気がさして、また別の事を <オイオイ
せっかく先日、サブマシンにもタブレットを接続したのだから、コレを活用しないのはもったいない、とのことで。
以前から集めてた情報に従い、タブレットをLinux(<サブマシン上で動作)に認識させるべく作業開始。
上手くいけば、Linux版の、軽〜いGIMPで遊べるナリ( ̄ー ̄)ニヤリ…
早速、XF86Configを修正して、再起動。
…なんか、「xxxxx xxxxxxxx failed」とか言ってるんですけど。
タブレット、完全に反応無し。
なんでやねん。
もしかして初代ArtPadだから? タブレット側の通信モードとして、ナントカIVをサポートしてること、とかドキュメントには書いてあるし。どうもそのへんが気になる。でも初代ArtPadがそもそもそれに相当するのかどうかもわからないし。資料も今時ドコにも置いてないしなぁ。
いや。またコレも、自分が何か設定してないのだろう。たぶん…

どれもこれも、先が見えない作業になりつつあるような。
(´Д`;)トホホ

1999/05/29() [n年前の日記]

#1 (NoTitle)なんか部屋の中がカメ...

なんか部屋の中がカメムシ臭い…。どっかから入ってきてどっかで勝手に潰れてんじゃないだろなぁ。(--;)

昨晩、従兄がこないだ差し入れに持ってきたペットボトルのコーヒーを飲んだら、なんだか体調が急激に悪化。うーん、コーヒーが飲めない体になってしまったみたい。

体調最悪ながらも教習所で2回目の実車操作。クラッチ操作が難しい…アクセル放してクラッチ踏んでローから(それはもういいって)。体で覚えるしかないんだろうなぁ。

以上、25 日分です。

過去ログ表示

Prev - 2024/04 - Next
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project